edkelly303/elm-nested-tuples/1.0.1

NOTE: the latest version is 1.0.3

NestedTuple

This library provides utility functions for working with nested tuples of the form:

( a, ( b, ( c, () ) ) ).

Primitives

empty : ()

Create an empty nested tuple.

cons : head -> tail -> ( head, tail )

Prepend a value to a nested tuple.

tail : ( head, tail ) -> tail

Get the tail (everything except the first element) of a nested tuple.

Note: From the four primitive functions empty, cons, head and tail, all the others can be derived.

In your own project, you might want to represent a nested tuple as something other than a tuple, for example:

  • type alias MyTuple a b = { head : a, tail : b }
  • type MyTuple a b = MyTuple a b

If so, you could just vendor this package and redefine these four functions for your preferred data type, then delete all the type annotations, and everything else should just work.

Utilities

singleton : head -> ( head, () )

Create a nested tuple with one element.

mapHead : (headA -> headB) -> ( headA, tail ) -> ( headB, tail )

Map over the head of a nested tuple.

mapTail : (tailA -> tailB) -> ( head, tailA ) -> ( head, tailB )

Map over the tail of a nested tuple.

Appenders, mappers and folders

define : a -> a

Begin the definition of an appender, mapper, or folder.

Appenders

appender : head -> (( head, tail ) -> toAppender) -> tail -> toAppender

Build up a nested tuple by appending values to the end of it.

This needs to be used in conjunction with define and endAppender:

import NestedTuple exposing (define, appender, endAppender)


define
    |> appender 1
    |> endAppender


--> ( 1, () )


define
    |> appender "hello"
    |> appender "world"
    |> endAppender


--> ( "hello", ( "world", () ) )
endAppender : (() -> appender) -> appender

Complete the definition of an appender.

Mappers

(headA -> headB)
-> ((( headA, tailA ) -> ( headB, tailB )) -> toMapper)
-> (tailA -> tailB)
-> toMapper

Create a mapper for a nested tuple by defining a map functions for each element of the tuple.

This needs to be used in conjunction with define and endMapper:

import NestedTuple exposing (define, mapper, endMapper)


double =
    define
        |> mapper (\int -> int * 2)
        |> mapper (\float -> float + float)
        |> endMapper


double ( 1, ( 1.5, () ) )


--> ( 2, ( 3.0, () ) )
endMapper : ((() -> ()) -> mapper) -> mapper

Complete the definition of a mapper.

(headA -> headB -> headC)
-> ( (( headA, tailA ) -> ( headB, tailB ) -> ( headC, tailC ))
-> toMapper2
)
-> (tailA -> tailB -> tailC)
-> toMapper2

Create a mapper for two nested tuples by defining map functions for each element of the tuples.

This needs to be used in conjunction with define and endMapper2:

import NestedTuple exposing (define, mapper2, endMapper2)


add =
    define
        |> mapper2 (\int1 int2 -> int1 + int2)
        |> mapper2 (\float1 float2 -> float1 + float2)
        |> endMapper2


add ( 1, ( 1.5, () ) )
    ( 2, ( 2.5, () ) )


--> ( 3, ( 4.0, () ) )
endMapper2 : ((() -> () -> ()) -> mapper2) -> mapper2

Complete the definition of a mapper2.

(headA -> headB -> headC -> headD)
-> ( ( ( headA, tailA )
-> ( headB, tailB )
-> ( headC, tailC )
-> ( headD, tailD )
)
-> toMapper3
)
-> (tailA -> tailB -> tailC -> tailD)
-> toMapper3

Create a mapper for three nested tuples by defining map functions for each element of the tuples.

This needs to be used in conjunction with define and endMapper3:

import NestedTuple exposing (define, mapper3, endMapper3)


add =
    define
        |> mapper3 (\int1 int2 int3 -> int1 + int2 + int3)
        |> mapper3 (\float1 float2 float3 -> float1 + float2 + float3)
        |> endMapper3


add ( 1, ( 1.5, () ) )
    ( 2, ( 2.5, () ) )
    ( 3, ( 3.5, () ) )


--> ( 6, ( 7.5, () ) )
endMapper3 : ((() -> () -> () -> ()) -> mapper3) -> mapper3

Complete the definition of a mapper3.

Folders

(head -> accForHead -> accForTail)
-> ((accForHead -> ( head, tail ) -> accForNext) -> toFolder)
-> (accForTail -> tail -> accForNext)
-> toFolder

Create a folder for a nested tuple by defining fold functions for each element of the tuple.

This needs to be used in conjunction with define and endFolder:

import NestedTuple exposing (define, folder, endFolder)


sum =
    define
        |> folder (\int acc -> int + acc)
        |> folder (\str acc -> String.length str + acc)
        |> endFolder


sum 0 ( 1, ( "foo", () ) )


--> 4
endFolder : ((acc -> empty -> acc) -> folder) -> folder

Complete the definition of a folder.

(headA -> headB -> accForHead -> accForTail)
-> ( (accForHead -> ( headA, tailA ) -> ( headB, tailB ) -> accForNext)
-> toFolder2
)
-> (accForTail -> tailA -> tailB -> accForNext)
-> toFolder2

Create a folder2 for two nested tuples by defining fold functions for each element of the tuples.

This needs to be used in conjunction with define and endFolder2:

import NestedTuple exposing (define, folder2, endFolder2)


sum =
    define
        |> folder2 (\int1 int2 acc -> int1 + int2 + acc)
        |> folder2 (\str1 str2 acc -> String.length (str1 ++ str2) + acc)
        |> endFolder2


sum 0
    ( 1, ( "foo", () ) )
    ( 2, ( "bar", () ) )


--> 9
endFolder2 : ((acc -> empty -> empty -> acc) -> folder2) -> folder2

Complete the definition of a folder2.

(headA -> headB -> headC -> accForHead -> accForTail)
-> ( ( accForHead
-> ( headA, tailA )
-> ( headB, tailB )
-> ( headC, tailC )
-> accForNext
)
-> toFolder3
)
-> (accForTail -> tailA -> tailB -> tailC -> accForNext)
-> toFolder3

Create a folder3 for three nested tuples by defining fold functions for each element of the tuples.

This needs to be used in conjunction with define and endFolder3:

import NestedTuple exposing (define, folder3, endFolder3)


sum =
    define
        |> folder3 (\int1 int2 int3 acc -> int1 + int2 + int3 + acc)
        |> folder3 (\str1 str2 str3 acc -> String.length (str1 ++ str2 ++ str3) + acc)
        |> endFolder3


sum 0
    ( 1, ( "foo", () ) )
    ( 2, ( "bar", () ) )
    ( 3, ( "baz", () ) )


--> 15
endFolder3 : ((acc -> empty -> empty -> empty -> acc) -> folder3) -> folder3

Complete the definition of a folder3.

Getters

{ focus : focus -> focus
, appendToGetters : getters -> getters
}

Begin the definition of a tuple of getters.

{ appendToGetters : ( tuple -> head, nextGetters ) -> toGetters
, focus : tuple -> ( head, tail )
}
-> { appendToGetters : nextGetters -> toGetters
, focus : tuple -> tail
}

Create a tuple of getters for a nested tuple.

This needs to be used in conjunction with defineGetters and endGetters:

import NestedTuple exposing (defineGetters, getter, endGetters)


defineGetters
    |> getter
    |> getter
    |> endGetters


--: ( ( a, ( b, () ) ) -> a
    , ( ( a, ( b, () ) ) -> b
      , () 
      ) 
    )
{ focus : focus
, appendToGetters : () -> getters
}
-> getters

Complete the definition of a tuple of getters.

Setters

{ focus : focus -> focus
, appendToSetters : setters -> setters
}

Begin the definition of a tuple of setters.

{ appendToSetters :
( head -> tuple -> tuple, nextSetters ) -> toSetters
, focus : (( head, tail ) -> ( head, tail )) -> tuple -> tuple
}
-> { appendToSetters : nextSetters -> toSetters
, focus : (tail -> tail) -> tuple -> tuple
}

Create a tuple of setters for a nested tuple.

This needs to be used in conjunction with defineSetters and endSetters:

import NestedTuple exposing (defineSetters, setter, endSetters)


defineSetters
    |> setter
    |> setter
    |> endSetters


--: ( a -> ( a, ( b, () ) ) -> ( a, ( b, () ) )
    , ( b -> ( a, ( b, () ) ) -> ( a, ( b, () ) )
      , () 
      ) 
    )
{ focus : focus
, appendToSetters : () -> setters
}
-> setters

Complete the definition of a tuple of setters.