laserpants/elm-burrito-update/2.3.0

NOTE: the latest version is 3.0.4

Burrito.Update

Monadic-style interface for state updates.

In standard use, you will not need the third type parameter of Update. See Burrito.Update.Simple in that case.

Update

type alias Update a msg t =
( a, List (Cmd msg), List t )

Type wrapper for Elm's ( model, Cmd msg ) tuple.

save : a -> Update a msg t

Lifts a value into the Update context. For example,

save model

corresponds to ( model, Cmd.none ) in code that doesn't use this library.

addCmd : Cmd msg -> a -> Update a msg t

Add a command to an Update pipeline. For example;

update msg state =
    case msg of
        SomeMsg someMsg ->
            state
                |> addCmd someCommand
                |> andThen (addCmd someOtherCommand)
                |> andThen (setStatus Done)

In this example, andThen (addCmd someOtherCommand) can also be shortened to andAddCmdsomeOtherCommand.

map : (a -> b) -> Update a msg t -> Update b msg t

Apply a function to the state portion of a value.

mapCmd : (msg -> msg1) -> Update a msg t -> Update a msg1 t

Map over the Cmd contained in the provided Update.

join : Update (Update a msg t) msg t -> Update a msg t

Remove one level of monadic structure. It may suffice to know that some other functions in this library are implemented in terms of join. In particular, andThen f = join << map f

kleisli : (b -> Update d msg t) -> (a -> Update b msg t) -> a -> Update d msg t

Right-to-left (Kleisli) composition of two functions that return Update values, passing the state part of the first return value to the second function.

Chaining Updates

andThen : (b -> Update a msg t) -> Update b msg t -> Update a msg t

Sequential composition of updates. This function is especially useful in combination with the forward pipe operator (|>), for writing code in the style of pipelines. To chain updates, we compose functions of the form something -> State -> Update State msg t:

say : String -> State -> Update State msg t
say what state = ...


save state
    |> andThen (say "hello")
    |> andThen doSomethingElse

Aside: andThen is like the monadic bind (>>=) operator in Haskell, but with the arguments interchanged.

sequence : List (a -> Update a msg t) -> a -> Update a msg t

Take a list of a -> Update a msg t values and run them sequentially, in a left-to-right manner.

Applicative Interface

These functions address the need to map over functions of more than one argument.

andMap : Update a msg t -> Update (a -> b) msg t -> Update b msg t

Trying to map over a function number -> number -> number,

map (+) (save 4)

we end up with a result of type Update (number -> number) msg t. To apply the function inside this value to another Update number msg t value, we can write…

map (+) (save 4) |> andMap (save 5)

in elm repl, we can verify that the result is what we expect:

> (map (+) (save 4) |> andMap (save 5)) == save 9
True : Bool

This pattern scales in a nice way to functions of any number of arguments:

let
    f x y z =
        x + y + z
in
map f (save 1)
    |> andMap (save 1)
    |> andMap (save 1)

If not sooner, you'll need this when you want to mapN and N > 7.

See also map2, map3, etc.

ap : Update (a -> b) msg t -> Update a msg t -> Update b msg t

This function is like andMap, but with the arguments interchanged.

map2 : (p -> q -> r) -> Update p msg t1 -> Update q msg t1 -> Update r msg t1

Apply a function of two arguments to the state portion of a value. Equivalently, we can think of this as taking a function a -> b -> c and transforming it into a “lifted” function of type Update a msg t -> Update b msg t -> Update c msg t.

(p -> q -> r -> s)
-> Update p msg t1
-> Update q msg t1
-> Update r msg t1
-> Update s msg t1

Apply a function of three arguments to the state portion of a value.

(p -> q -> r -> s -> t)
-> Update p msg t1
-> Update q msg t1
-> Update r msg t1
-> Update s msg t1
-> Update t msg t1

Apply a function of four arguments to the state portion of a value.

(p -> q -> r -> s -> t -> u)
-> Update p msg t1
-> Update q msg t1
-> Update r msg t1
-> Update s msg t1
-> Update t msg t1
-> Update u msg t1

Apply a function of five arguments to the state portion of a value.

(p -> q -> r -> s -> t -> u -> v)
-> Update p msg t1
-> Update q msg t1
-> Update r msg t1
-> Update s msg t1
-> Update t msg t1
-> Update u msg t1
-> Update v msg t1

Apply a function of six arguments to the state portion of a value.

(p -> q -> r -> s -> t -> u -> v -> w)
-> Update p msg t1
-> Update q msg t1
-> Update r msg t1
-> Update s msg t1
-> Update t msg t1
-> Update u msg t1
-> Update v msg t1
-> Update w msg t1

Apply a function of seven arguments to the state portion of a value.

Program Integration

run : (p -> Update a msg t) -> p -> ( a, Cmd msg )

Translate a function that returns an Update into one that returns a plain ( model, cmd ) pair.

run2 : (p -> q -> Update a msg t) -> p -> q -> ( a, Cmd msg )

Same as run, but for functions of two arguments.

run3 : (p -> q -> r -> Update a msg t) -> p -> q -> r -> ( a, Cmd msg )

Same as run, but for functions of three arguments.

Helpers

andAddCmd : Cmd msg -> Update a msg t -> Update a msg t

Shortcut for andThen << addCmd

using : (a -> a -> b) -> a -> b

Combinator useful for pointfree style. For example;

nextPage state =
    goToPage (state.current + 1) state

can be changed to

nextPage =
    using (\{ current } -> goToPage (current + 1))
with : (a -> b) -> (b -> a -> c) -> a -> c

Combinator useful for pointfree style. For example, to get rid of the lambda in the following code;

update msg state =
    case msg of
        Click ->
            state
                |> updateSomething
                |> andThen (\s -> setCounterValue (s.counter + 1) s)

we can write:

update msg state =
    case msg of
        Click ->
            state
                |> updateSomething
                |> andThen (with .counter (setCounterValue << (+) 1))
andWith : (b -> c) -> (c -> b -> Update a msg t) -> Update b msg t -> Update a msg t

Shortcut for \fun -> andThen << with fun

andUsing : (b -> b -> Update a msg t) -> Update b msg t -> Update a msg t

Shortcut for andThen << using