xilnocas/step/4.0.2

NOTE: the latest version is 4.1.4

Renamed to nicklawls/step. That is where the repository lives now. It has not been published as a package under the new name.

Versions published as xilnocas/step still install under that name. 11 versions of 15 come from the new location (see their notes).

Rerouted (renamed, verified). The GitHub user or repository was renamed. The tag is still there, at the new name. The Lamdera package server serves a copy recovered from https://github.com/nicklawls/step.

What we checked: The repo moved to github.com/nicklawls/step. Rebuilt with git archive from commit 114df5ea0b2f of https://github.com/nicklawls/step (zip prefix xilnocas-step-114df5e/, America/Los_Angeles times): the zip is byte-identical to the one package.elm-lang.org recorded, SHA-1 c37d25ab990fc83d3d106b70bee2ed4e51e1525e.

The Lamdera compiler uses this copy and prints a one-line notice saying so. elm itself fails to download this version.

Details · package.elm-lang.org's zip: https://github.com/xilnocas/step/zipball/4.0.2/

elm-state-transition

An experimental library for cleaner, more composable update functions

Installation

elm package install xilnocas/elm-state-transition

Usage

This library deals with state transitions, a fancy term for the act of updating the state of your application. Any time your app steps from one state to another, It's undergone a state transition. In an elm app, state transitions happen in response to messages. The update function is what tells Elm how to transition the state of your app when a given message fires. So, at the code level, this lbrary deals with writing update functions.

The idea is that instead of returning a (Model, Cmd Msg) from your update function, you'll return a Step Model Msg a, with or without the a variable filled in. I know, I know, there are three type variables there. I'd like there to be fewer, but they're just too darn useful! In return for having to look at three freakin type variables all day long, you'll get an API that should look familiar if you've been doing elm for a while, and lets you encode a bunch of common update function patterns very succinctly.

At least as importantly, I believe the library expresses these patterns in a way that's less about the visual "components" in your app, and more about the underlying interactions, and helping them have as little state as possible. That way, you can leave all the visual detail for your view function, where it belongs! Here are a few quick examples of what I'm talking about:

Step.map

Step.map works just like map from Maybe and Result. It lets a Step returned from one update function become part of an update function that calls it. If you have update functions with a lot of let expressions, you're going to like this function. Step.mapMsg works the same way, but for the second type variable.

Step.stay

Step.stay is sort of like Nothing, but specialized for Steps. It lets you say "on this combination of Model and Msg, I don't want the state to transition. When used in combination with Step.orElse, it lets you combine a bunch of isolated steps, and return only the first one that isn't a stay

Step.exit

Step.exit and Step.onExit work together to implement a version of what's sometimes called the "OutMsg" pattern, which is really just returning context other than the (Model, Cmd Msg) from an update function. A special case of that pattern that I've found really useful is when the context only comes out when update function makes its final transition. Think of a login interaction: It starts, proceeds as the user gets types their info, then some REST call is made, then when all is said and done we're left with a User. We can encode that idea really easily:

module Login exposing (..)


update : Msg -> Model -> Step Model Msg User
update msg model = 
        case msg of 
           LoginSucceeded user -> Step.exit user
        
        ...

Then, whoever uses our Login module can use Step.onExit to incorporate this returned data into their own Step

module Main exposing (..)

import Login


update : Msg -> Model -> Step Model Msg a
update msg model = 
     case (msg, model) of 
         (LoginMsg loginMsg, LoggingIn loginModel) -> 
            Login.update loginMsg loginModel
                |> Step.map LoggingIn
                |> Step.mapMsg LoginMsg
                |> Step.onExit (\user ->  Step.to (LoggedIn user) )
         ...

My hunch is that this method of building update functions around some piece of data that gets built as the result of a stateful interaction covers most of the use cases of the "OutMsg" pattern, and ulitmately leads to simpler, easier to understand code. I'm excited so see if the community finds this to be true as well!