This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
Extend Return with Monocle's Lenses for fun in the update function
version 1.1.1
license BSD3
native-modules False
elm-version 0.18.0 <= v < 0.19.0
Tag 1.1.1
Committed At 2017-04-04 16:25:27 UTC
elm-lang/core 5.0.0 <= v < 6.0.0 5.1.1
arturopala/elm-monocle 1.4.0 <= v < 2.0.0 1.7.0
Fresheyeball/elm-return 6.0.3 <= v < 7.0.0 6.0.3

Modules

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.

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

module Model exposing (Model)

import Checkbox.Model as Checkbox


type alias Model =
    { pageTitle : String
    , checkbox : Checkbox.Model
    }
module Checkbox.Model exposing (Model)

type alias Model =
    { checked : Bool
    }

Msgs

module Msg exposing (Msg(..))

import Checkbox.Msg as Checkbox


type Msg
    = TitleChange String
    | CheckboxMsg Checkbox.Msg
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

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
                          ]
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 Lenses we can instead change our model files and our update files like this:

module Model exposing (..)

import Monocle.Lens exposing (Lens)
import Checkbox.Model as Checkbox


type alias Model =
    { pageTitle : String
    , checkbox : Checkbox.Model
    }


pageTitle : Lens Model String
pageTitle =
    Lens .pageTitle <| \p m -> { m | pageTitle = p }


checkbox : Lens Model Checkbox.Model
checkbox =
    Lens .checkbox <| \c m -> { m | checkbox = c }
module Checkbox.Model exposing (..)

import Monocle.Lens exposing (Lens)


type alias Model =
    { checked : Bool
    }


checked : Lens Model Bool
checked =
    Lens .checked <| \c m -> { m | checked = c }
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 model =
    let
        cmdWeAlwaysDo : Cmd Msg
        cmdWeAlwaysDo =
            -- insert a real command in a non-toy app
            Cmd.none
    in
        Return.singleton model
            |> Return.command cmdWeAlwaysDo
            |> case msg of
                TitleChange title ->
                    Return.map <| .set Model.pageTitle title

                -- Note how much more condensed this part is
                CheckboxMsg cbMsg ->
                    refractl Model.checkbox CheckboxMsg <|
                      Checkbox.update cbMsg
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 model =
    Return.singleton model
        |> case msg of
            CheckMe bool ->
                Return.map <| .set Model.checked = bool