Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/toastal/return-optics
Extending Return with Lenses to do fun things in the Elm update function
https://github.com/toastal/return-optics
elm optics return
Last synced: 2 months ago
JSON representation
Extending Return with Lenses to do fun things in the Elm update function
- Host: GitHub
- URL: https://github.com/toastal/return-optics
- Owner: toastal
- License: bsd-3-clause
- Created: 2016-10-21T03:29:51.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2017-10-28T22:39:44.000Z (about 7 years ago)
- Last Synced: 2024-10-01T09:19:48.819Z (3 months ago)
- Topics: elm, optics, return
- Language: Elm
- Homepage: http://package.elm-lang.org/packages/toastal/return-optics/latest
- Size: 11.7 KB
- Stars: 13
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Return.Optics
`Return.Optics` is a utility library extending `Return` with `Monocle` making a clean, concise API for doing Elm component updates in the context of other updates. Initially it includes helper functions around refraction—the bending of light. Like viewing a straw being inserted into a glass of water, we’ll use a `Lens` to bend our top-level update function into our component update, and when we pull it out, well be left with an unbent `( model, Cmd msg )` of the Elm architecture.
If you would like a more in-depth read into why, you can read about that on [my blog](https://toast.al/posts/2016-10-20-optical-swordplay-with-components.html).
However, if that’s not your thing and doesn’t make sense, you’re in luck because we’re about to go over an example.
Suppose we have this trivial, toy component and model…
#### Models
```elm
module Model exposing (Model)import Checkbox.Model as Checkbox
type alias Model =
{ pageTitle : String
, checkbox : Checkbox.Model
}
``````elm
module Checkbox.Model exposing (Model)type alias Model =
{ checked : Bool
}
```#### Msgs
```elm
module Msg exposing (Msg(..))import Checkbox.Msg as Checkbox
type Msg
= TitleChange String
| CheckboxMsg Checkbox.Msg
``````elm
module Checkbox.Msg exposing (Msg(..))type Checkbox
= CheckMe Bool
```Assuming we have built up some `cmdWeAlwaysDo`, with the standard library we’d write updates like this:
#### Stardard Updates
```elm
module Update exposing (update)import Checkbox.Update as Checkbox
import Model
import Msg exposing (Msg(TitleChange, CheckboxMsg))update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
let
cmdWeAlwaysDo : Cmd Msg
cmdWeAlwaysDo =
-- insert a real command in a non-toy app
Cmd.none
in
case msg of
TitleChange title ->
( { model | pageTitle = title }, cmdWeAlwaysDo )CheckboxMsg cbMsg ->
let
( cbModel, cbCmd )
Checkbox.Update cbMsg model.checkbox
in
{ model | checkbox = cbModel }
! [ cbCmd
, cmdWeAlwaysDo
]
``````elm
module Checkbox.Update exposing (update)import Checkbox.Model as Model
import Checkbox.Msg as Msg exposing (Msg(CheckMe))update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
CheckMe bool ->
{ model | checked = bool }
```- - -
Using `Return.Optics.refractl` and `Lens`es we can instead change our model files and our update files like this:
```elm
module Model exposing (..)import Monocle.Lens exposing (Lens)
import Checkbox.Model as Checkboxtype alias Model =
{ pageTitle : String
, checkbox : Checkbox.Model
}pageTitlel : Lens Model String
pageTitlel =
Lens .pageTitle (\p m -> { m | pageTitle = p })checkboxl : Lens Model Checkbox.Model
checkboxl =
Lens .checkbox (\c m -> { m | checkbox = c })
``````elm
module Checkbox.Model exposing (..)import Monocle.Lens exposing (Lens)
type alias Model =
{ checked : Bool
}checkedl : Lens Model Bool
checkedl =
Lens .checked (\c m -> { m | checked = c })
``````elm
module Update exposing (update)import Return exposing (Return)
import Return.Optics exposing (refractl)
import Checkbox.Update as Checkbox
import Model
import Msg exposing (Msg(TitleChange, CheckboxMsg))update : Msg -> Model -> Return Msg Cmd
update msg =
let
cmdWeAlwaysDo : Cmd Msg
cmdWeAlwaysDo =
-- insert a real command in a non-toy app
Cmd.none
in
Return.singleton
>> Return.command cmdWeAlwaysDo
>> case msg of
TitleChange title ->
Return.map (.set Model.pageTitlel title)-- Note how much more condensed this part is
CheckboxMsg cbMsg ->
refractl Model.checkboxl CheckboxMsg (Checkbox.update cbMsg)
``````elm
module Checkbox.Update exposing (update)import Checkbox.Model as Model
import Checkbox.Msg as Msg exposing (Msg(..))update : Msg -> Model -> Return Msg Model
update msg =
Return.singleton
>> case msg of
CheckMe bool ->
Return.map (.set Model.checkedl bool)
```