Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fresheyeball/elm-return
Writer powered pipelining for `(model, Cmd msg)`
https://github.com/fresheyeball/elm-return
Last synced: 7 days ago
JSON representation
Writer powered pipelining for `(model, Cmd msg)`
- Host: GitHub
- URL: https://github.com/fresheyeball/elm-return
- Owner: Fresheyeball
- License: bsd-3-clause
- Created: 2016-06-11T03:18:49.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2022-09-26T12:18:34.000Z (about 2 years ago)
- Last Synced: 2024-10-30T01:38:15.555Z (8 days ago)
- Language: Elm
- Homepage:
- Size: 11.2 MB
- Stars: 82
- Watchers: 5
- Forks: 4
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Return
When writing Elm code you unavoidably have to interact with types like this:
```elm
( model, Cmd msg )
```This library makes that a Type:
```elm
type alias Return msg model =
( model, Cmd msg )
```You can interact with `Return` in terms of the `Model`, and trust that `Cmd`s
get tracked and batched together automatically. Letting you focus on composing
transformations on `Return` without manually shuffling around `Cmd`.## Examples
Lets say we have a situation where we have a top level `update` function
and wish to embed a component's `update` function.```elm
type Model
= HomeMod Home.Model
| AboutMod About.Modeltype Msg
= HomeMsg Home.Msg
| AboutMsg About.Msgupdate : Msg -> Model -> (Model, Cmd Msg)
update msg model =
let
(updateModel, updateCmd) =
case (model, msg) of
(HomeMod model_, HomeMsg msg_) ->
let
(subModel, subCmd) =
Home.update msg_ model_in
( HomeMod subModel, Cmd.map HomeMsg subCmd )(AboutMod model_, AboutMsg msg_) ->
let
(subModel, subCmd) =
About.update msg_ model_in
( AboutMod subModel, Cmd.map AboutMsg subCmd )x ->
let
_ =
Debug.log "Stray found" xin
( model, Cmd.none )transformed =
Route.alwaysTranfromModelWithMe updateModelin
( transformed
, Cmd.batch
[ updateCmd
, alwaysDoMeCmd
, conditionallyDoSomething transformed
]
)
```The code above is good, but it suffers in some areas. For example
we could forget to include `updateCmd` in the final `in` expression,
and those side effects are lost. Or we could neglect to put the
final *third* version of the model, `transformed`, into `conditionallyDoSomething`.
That and there is a big dependence on pattern matching and literals,
which does not lend itself well to pipelining.Lets see how we can clean this up with `Return`.
```elm
type Model
= HomeMod Home.Model
| AboutMod About.Modeltype Msg
= HomeMsg Home.Msg
| AboutMsg About.Msgupdate : Msg -> Model -> Return Msg Model
update msg model =
(case (model, msg) of
( HomeMod model_, HomeMsg msg_ ) ->
Home.update msg_ model_
|> mapBoth HomeMsg HomeMod( AboutMod model_, AboutMsg msg_ ) ->
About.update msg_ model_
|> mapBoth AboutMsg AboutModx ->
let
_ =
Debug.log "Stray found" xin
singleton model)
|> command alwaysDoMeCmd
|> map Route.alwaysTranfromModelWithMe
|> effect_ conditionallyDoSomething
```The cleaned up code is not only more succinct, and more imperative (in a good way),
but it doesn't suffer from the problems described above. There is no risk of mixing up
your terms or accidentally dropping a cmd.