Heimdell/elm-optics/2.0.0

NOTE: the latest version is 3.0.1

What

Minimalistic, but faithful port of Lens to Elm.

This library provides a way to access and modify elements of data located deeply inside a structure, possibly behind sum types (Maybe, Either, etc) and/or containers (Array, List, Dict, Tuple, etc). There also are ways to define custom accessors for your own types and compose them with a single o operator as you like.

Example

Imports

import Optics.Basic exposing (..)
import Optics.Core exposing (..)
import Dict exposing (Dict)

Data

type alias Point = { x : Float, y : Float }

type alias Block = { mass : Float, components : List (Maybe Point, String) }

type alias Model = Dict String Block

Accessors

y_ : SimpleLens ls { a | y : b } b
y_ = lens .y <| \s a -> { s | y = a }

components_ : SimpleLens ls { a | components : b } b
components_ = lens .components <| \s a -> { s | components = a }

Reading

theHighestPoint : Model -> Maybe Float
theHighestPoint model =
    model
    |> getAll (o dictValues (o components_ (o each (o first (o just_ y_)))))
    |> List.maximum

Updating

moveVertically : Float -> Model -> Model
moveVertically dy model =
    model
    |> update
        (o (o dictValues components_) (o each (o first (o just_ y_))))
        (\y -> y + dy)

Workflow

You create accessor using optics from Optics.Basic and your own (created by lens, prism, etc from Optics.Core) using composition operator Optics.Core.o.

Then you use it with functions like get, getSome, getAll, update or assign.

The o operator is associative, so (o a (o b c)) is the same as (o (o a b) c).

Gory details

The one new exported type it defines is

type Optic pr ls s t a b = ...
```.

The `pr` and `ls` are types for proofs that given optic is a "Prism" or a "Lens".
The proof types that are used are not accessible outside the library, so if you must leave there vars to be type variables in your code.

For instance, the type synonym
```elm
type alias Lens ls s t a b = Optic N ls s t a b

disables "Prism" behaviour for lens by setting prism proof type as inconstructible type N.

The o operator has type

o : Optic pr ls s t a b -> Optic pr ls a b x z -> Optic pr ls s t z s

so it will, if a lens is on either side, unify pr variable of the second optic with N.

Basically, N will contaminate any o chains in a given channel, making some eliminators impossibe to use.

Same goes for prisms - ls is set to N.

The traversal is when both ls and pr are set to N - for instance, by creating one with traversal or by composing a prism with a lens in either direction (e.g. o first _Just).

The lens/prism-specific eliminators for the optics (get/review/is) are requiring that the pr (or ls) should be ().