xilnocas / step / Step

Steps and how to make them


type Step model msg a

A Step model msg a describes one state transition of an application, and is intended to be what gets returned from an update function.

It's helpful to look at how a Step is (roughly) represented under the hood

type Step model msg a
    = To model (Cmd msg)
    | Exit a
    | Stay

We provide a smart constructor for each of these variants, but we hide the internal representation to make sure you're not pattern matching on Steps willy-nilly.

That being said, if you find something that makes you want the data structure fully exposed, please make an issue on GitHub!

to : model -> Step model msg a

Transition to a new state, without executing any commands

stay : Step model msg a

Keep the interaction in the state it was in.

Note: This will prevent any commands from being returned

Step.stay == (Step.stay |> Step.withCmd myHttpCall)

If you want to stay in the same state, but run some commands, use Step.to explicitly

Step.to MySameState |> Step.withCmd myHttpCall

exit : a -> Step model msg a

End the interaction by returning a value of type a

fromUpdate : ( model, Platform.Cmd.Cmd msg ) -> Step model msg o

Build a Step from a normal elm update tuple

fromMaybe : Maybe model -> Step model msg a

Step to the state denoted by the model in the Just case, stay otherwise

Issuing commands

withCmd : Platform.Cmd.Cmd msg -> Step model msg a -> Step model msg a

If we're stepping to a new state, add an cmd to fire off

This can be called on a Step multiple times, and all the commands will fire.

No commands are fired if the Step turns out to be a stay or an exit

Alternate name ideas:

withAttempt : (Result x a -> msg) -> Task x a -> Step model msg b -> Step model msg b

A helper for building Steps out of tasks

command : Platform.Cmd.Cmd msg -> Step model msg a -> Step model msg a

Experimental alias for withCmd

attempt : (Result x a -> msg) -> Task x a -> Step model msg b -> Step model msg b

Experimental alias for withAttempt

Transforming and Composing Steps

All of these functions help you build functions that return steps out of other functions that return steps

map : (model1 -> model2) -> Step model1 msg a -> Step model2 msg a

Apply a function to the state inside a Step, if it's there

Most useful for building a Step out of another Step returned from some other update function you're calling

mapMsg : (msg1 -> msg2) -> Step model msg1 a -> Step model msg2 a

Apply a function to any msgs in the Step's commands

Often used alongside map for building "bigger" Steps out of "smaller" ones

within : (model1 -> model2) -> (msg1 -> msg2) -> Step model1 msg1 a -> Step model2 msg2 a

Use a step "within" a larger interaction

Step.within f g = Step.map f >> Step.mapMsg g

mapExit : (a -> b) -> Step model msg a -> Step model msg b

Map over the output of an interaction, if we've reached the end

orElse : Step model msg a -> Step model msg a -> Step model msg a

Run the first suceeding Step, with priority given to the second argument

Intended to be used pipeline style

Step.to { loading = True } |> Step.orElse (Step.to { loading = False }) == Step.to { loading = True }

Step.noop |> Step.orElse Step.to { loading = True } == Step.to { loading = True }

onExit : (a -> Step model msg b) -> Step model msg a -> Step model msg b

Choose a Step based on the result of another interaction

You can use this in combination with map and mapMsg to glue the end of one interaction to the beginning of another.

Notice that it looks a lot like Maybe.andThen and Result.andThen, but operating on the last type variable.

Getting back to TEA land

run : Step model msg Basics.Never -> Maybe ( model, Platform.Cmd.Cmd msg )

Turn a Step into the usual TEA update tuple

It must be a Step that doesn't exit. We know it is if the type variable a is still lowercase, i.e. not a specifc type, and can thus be chosen to be Never when calling this function.

asUpdateFunction : (msg -> model -> Step model msg Basics.Never) -> msg -> model -> ( model, Platform.Cmd.Cmd msg )

Turn an update function that returns a Step to a normal Elm Architecture update function

uses run internally to default with the provided model in case of a stay

Testing update functions

foldSteps : (msg -> model -> Step model msg a) -> ( model, Platform.Cmd.Cmd msg ) -> List msg -> Step model msg a

Starting from an initial state, fold an update function over a list of messages

Only use this to test that the application of certain messages produces the result you expect. In application code, building up a bunch of Msgs just to feed them to an update function is ususally not worth the effort.