# More useful program combinators

**URL:** <https://discourse.elm-lang.org/t/more-useful-program-combinators/648>\
**Category:** Learn\
**Created:** [February 7, 2018, 3:04pm UTC](https://discourse.elm-lang.org/t/more-useful-program-combinators/648 "2018-02-07T15:04:33Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [February 7, 2018, 3:04pm UTC](https://discourse.elm-lang.org/t/more-useful-program-combinators/648/1 "2018-02-07T15:04:33Z")

</div>

So these are not actually program combinators, as they leave out the other parts other than `update`. But it mostly seems that when I combine packages of re-usable code together, its the update functions that present an opportunity to make use of some helper functions to trim the boilerplate.

I took this `lift` function from [elm-mdl/Material.Helpers](http://package.elm-lang.org/packages/debois/elm-mdl/8.1.0/Material-Helpers) (but switched around the set function to follow the convention of ‘model goes last’):

```
lift :
    (model -> submodel)
    -> (submodel -> model -> model)
    -> (submsg -> msg)
    -> (submsg -> submodel -> ( submodel, Cmd sub msg ))
    -> submsg
    -> model
    -> ( model, Cmd msg )
lift get set tagger update subMsg model =
    let
        ( updatedSubModel, subCmd ) =
            update subMsg (get model)
    in
        ( set updatedSubModel model, Cmd.map tagger subCmd )

```

And I based this `eval` function on what I saw in [folkertdev/OutMessage](http://package.elm-lang.org/packages/folkertdev/outmessage/1.1.1/OutMessage)

```
eval :
    (model -> ( model, Cmd msg ))
    -> ( model, Cmd msg )
    -> ( model, Cmd msg )
eval func ( model, cmds ) =
    let
        ( newModel, moreCmds ) =
            func model
    in
        ( newModel, Cmd.batch [cmds, moreCmds] )

```

It only differs from `Tuple.mapSecond` in that it appends the commands together using `Cmd.batch`.

I also note that it is possible to write another lift function, for the case where update functions return 3 values, one of them being an _out message_, which is equivalent to code like this:

```
Auth.update msg model.auth
    |> OutMessage.mapComponent (\auth -> { model | auth = auth })
    |> OutMessage.mapCmd AuthMsg

```

I like how this reduces the language of combining update functions to _lift_ and _eval_.

---

<div class="post-metadata">

**Author:** ![rofrol](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rofrol/32/60_2.png) [@rofrol](https://discourse.elm-lang.org/u/rofrol)\
**Post date:** [February 7, 2018, 3:49pm UTC](https://discourse.elm-lang.org/t/more-useful-program-combinators/648/2 "2018-02-07T15:49:08Z")

</div>

Is it similar to what is in [https://github.com/rtfeldman/elm-spa-example](https://github.com/rtfeldman/elm-spa-example)?

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [February 7, 2018, 4:48pm UTC](https://discourse.elm-lang.org/t/more-useful-program-combinators/648/3 "2018-02-07T16:48:11Z")

</div>

> [@rofrol](#):
>
> Is it similar to what is in [GitHub - rtfeldman/elm-spa-example: A Single Page Application written in Elm](https://github.com/rtfeldman/elm-spa-example)?

No, not really. elm-spa-example does make use of nested updates to bring together all the pages into the top-level update function, but it codes whatever it needs to fit its own situation. I also don’t think I saw any out messages in elm-spa-example.

I’m just trying to discover a pattern, by looking at how I tend to nest updates in my own code, then package up the re-usable bit of the pattern. That gives me a short hand for combing update functions into the top-level one.
