Accessors are a way of operating on nested data in Elm that doesn't require gobs of boilerplate.
The isomorphism is both "lens" and "prism".
Lens that cannot change type of the object.
Prism that cannot change the type of the object.
Traversal that cannot change the type of the object.
Accessors are built using these functions:
This exposes a description field that's necessary for use with the name function for getting unique names out of compositions of accessors. This is useful when you want type safe keys for a Dictionary but you still want to use elm/core implementation.
each : Optic pr ls a b x y -> Traversal (List a) (List b) x y
each =
Base.traversal "[]"
identity
List.mapThis exposes a description field that's necessary for use with the name function for getting unique names out of compositions of accessors. This is useful when you want type safe keys for a Dictionary but you still want to use elm/core implementation.
foo : Optic attr view over -> Optic { rec | foo : attr } view over
foo =
makeOneToOne
".foo"
.foo
(\change rec -> { rec | foo = change rec.foo })A prism constructor.
Parameters are: reconstructor and a splitter.
Reconstructor takes a final value and constructs a final object.
The splitter turns initial object either to final object directly (if initial object is of wrong variant),
or spits out a.
An isomorphism constructor.
Action functions are functions that take an accessor and let you perform a specific action on data using that accessor.
The get function takes:
super
and returns the value accessed by that combinator.get (foo << bar) myRecordUsed with a Prism, think of !! boolean coercion in Javascript except type safe.
Just "Stuff"
|> all just
--> ["Stuff"]
Nothing
|> all just
--> []Used with a Prism, think of !! boolean coercion in Javascript except type safe.
["Stuff", "things"]
|> try (at 2)
--> Nothing
["Stuff", "things"]
|> try (at 0)
--> Just "Stuff"Used with a Prism, think of !! boolean coercion in Javascript except type safe.
Just 1234
|> has just
--> True
Nothing
|> has just
--> False
[ "Wooo", "Things" ]
|> has (at 7)
--> False
[ "Wooo", "Things" ]
|> has (at 0)
--> Truealias for has
The map function takes:
(sub -> sub),super
and it returns the data structure, with the accessible field changed by applying
the function to the existing value.map (foo << qux) ((+) 1) myRecordalias for map
over (foo << qux) ((+) 1) myRecordThe set function takes:
sub,super
and it returns the data structure, with the accessible field changed to be
the set value.set (foo << bar) "Hi!" myRecordUse prism to reconstruct.
This function gives the name of the function as a string...
Alias of get for isomorphisms
Get the inverse of an isomorphism
Lift an optic over an indexed traversal
The isomorphism is both "lens" and "prism".
The lens is "not a prism".
The prism is "not a lens".
The traversal is neither "lens" or "prism".
This MUST be a Prism or Iso
This MUST be a Prism or Iso
This MUST be a non-type changing Lens or Iso
This MUST be a non-type changing Prism or Iso
Any Optic
This MUST be a Prism or Iso
This MUST be a Lens or Iso
This MUST be a Prism or Iso
import noise. Not everything is re-exported.This accessor combinator lets you access values inside Maybe.
import Accessors exposing (..)
import Lens as L
maybeRecord : { foo : Maybe { bar : Maybe {stuff : Maybe Int} }, qux : Maybe { bar : Maybe Int } }
maybeRecord = { foo = Just { bar = Just { stuff = Just 2 } }
, qux = Nothing
}
try (L.foo << just << L.bar << just << L.stuff) maybeRecord
--> Just (Just 2 )
try (L.qux << just << L.bar) maybeRecord
--> Nothing
map (L.foo << just << L.bar << just << L.stuff << just) ((+) 1) maybeRecord
--> {foo = Just {bar = Just { stuff = Just 3 }}, qux = Nothing}
map (L.qux << just << L.bar << just) ((+) 1) maybeRecord
--> {foo = Just {bar = Just {stuff = Just 2}}, qux = Nothing}This accessor lets you access values inside the Ok variant of a Result.
alias for Result.Accessors.onOk
import Accessors exposing (..)
import Lens as L
maybeRecord : { foo : Result String { bar : Int }, qux : Result String { bar : Int } }
maybeRecord = { foo = Ok { bar = 2 }
, qux = Err "Not an Int"
}
try (L.foo << ok << L.bar) maybeRecord
--> Just 2
try (L.qux << ok << L.bar) maybeRecord
--> Nothing
map (L.foo << ok << L.bar) ((+) 1) maybeRecord
--> { foo = Ok { bar = 3 }, qux = Err "Not an Int" }
map (L.qux << ok << L.bar) ((+) 1) maybeRecord
--> { foo = Ok { bar = 2 }, qux = Err "Not an Int" }This accessor lets you access values inside the Err variant of a Result.
alias for Result.Accessors.onErr
import Accessors exposing (..)
import Lens as L
maybeRecord : { foo : Result String { bar : Int }, qux : Result String { bar : Int } }
maybeRecord = { foo = Ok { bar = 2 }
, qux = Err "Not an Int"
}
try (L.foo << err) maybeRecord
--> Nothing
try (L.qux << err) maybeRecord
--> Just "Not an Int"
map (L.foo << err) String.toUpper maybeRecord
--> { foo = Ok { bar = 2 }, qux = Err "Not an Int" }
map (L.qux << err) String.toUpper maybeRecord
--> { foo = Ok { bar = 2 }, qux = Err "NOT AN INT" }values: This accessor lets you traverse a Dict including the index of each element
alias for Dict.Accessors.each
import Accessors exposing (..)
import Lens as L
import Dict exposing (Dict)
dictRecord : {foo : Dict String {bar : Int}}
dictRecord = { foo = [ ("a", { bar = 2 })
, ("b", { bar = 3 })
, ("c", { bar = 4 })
] |> Dict.fromList
}
all (L.foo << values) dictRecord
--> [{bar = 2}, {bar = 3}, {bar = 4}]
map (L.foo << values << L.bar) ((*) 10) dictRecord
--> {foo = [("a", {bar = 20}), ("b", {bar = 30}), ("c", {bar = 40})] |> Dict.fromList}
all (L.foo << values << L.bar) dictRecord
--> [2, 3, 4]
map (L.foo << values << L.bar) ((+) 1) dictRecord
--> {foo = [("a", {bar = 3}), ("b", {bar = 4}), ("c", {bar = 5})] |> Dict.fromList}keyed: This accessor lets you traverse a Dict including the index of each element
alias for Dict.Accessors.eachIdx
import Accessors exposing (..)
import Lens as L
import Dict exposing (Dict)
dictRecord : {foo : Dict String {bar : Int}}
dictRecord = { foo = [ ("a", { bar = 2 })
, ("b", { bar = 3 })
, ("c", { bar = 4 })
] |> Dict.fromList
}
multiplyIfA : (String, { bar : Int }) -> { bar : Int }
multiplyIfA ( key, ({ bar } as rec) ) =
if key == "a" then
{ bar = bar * 10 }
else
rec
all (L.foo << keyed) dictRecord
--> [("a", {bar = 2}), ("b", {bar = 3}), ("c", {bar = 4})]
map (L.foo << keyed) multiplyIfA dictRecord
--> {foo = [("a", {bar = 20}), ("b", {bar = 3}), ("c", {bar = 4})] |> Dict.fromList}
all (L.foo << keyed << ixd L.bar) dictRecord
--> [2, 3, 4]
map (L.foo << keyed << ixd L.bar) ((+) 1) dictRecord
--> {foo = [("a", {bar = 3}), ("b", {bar = 4}), ("c", {bar = 5})] |> Dict.fromList}key: NON-structure preserving accessor over Dict's
alias for Dict.Accessors.at
In terms of accessors, think of Dicts as records where each field is a Maybe.
import Dict exposing (Dict)
import Accessors exposing (..)
import Lens as L
dict : Dict String {bar : Int}
dict = Dict.fromList [("foo", {bar = 2})]
get (key "foo") dict
--> Just {bar = 2}
get (key "baz") dict
--> Nothing
try (key "foo" << just << L.bar) dict
--> Just 2
set (key "foo") Nothing dict
--> Dict.remove "foo" dict
set (key "baz" << just << L.bar) 3 dict
--> dictkey: NON-structure preserving accessor over Dict's
alias for Dict.Accessors.id
In terms of accessors, think of Dicts as records where each field is a Maybe.
import Dict exposing (Dict)
import Accessors exposing (..)
import Lens as L
dict : Dict Int {bar : Int}
dict = Dict.fromList [(1, {bar = 2})]
get (keyI 1) dict
--> Just {bar = 2}
get (keyI 0) dict
--> Nothing
try (keyI 1 << just << L.bar) dict
--> Just 2
set (keyI 1) Nothing dict
--> Dict.remove 1 dict
set (keyI 0 << just << L.bar) 3 dict
--> dictkey_: NON-structure preserving accessor over Dict's
alias for Dict.Accessors.at_
In terms of accessors, think of Dicts as records where each field is a Maybe.
import Dict exposing (Dict)
import Accessors exposing (..)
import Lens as L
dict : Dict Char {bar : Int}
dict = Dict.fromList [('C', {bar = 2})]
keyC : Char -> Lens ls (Dict Char { bar : Int }) (Maybe { bar : Int }) x y
keyC =
key_ String.fromChar
get (keyC 'C') dict
--> Just {bar = 2}
get (keyC 'Z') dict
--> Nothing
try (keyC 'C' << just << L.bar) dict
--> Just 2
set (keyC 'C') Nothing dict
--> Dict.remove 'C' dict
set (keyC 'Z' << just << L.bar) 3 dict
--> dictThis accessor combinator lets you access values inside List.
alias for List.Accessors.each
This accessor lets you traverse a list including the index of each element
alias for List.Accessors.eachIdx
at: Structure Preserving accessor over List members.
alias for List.Accessors.at
This accessor combinator lets you access values inside Array.
alias for Array.Accessors.each
import Accessors exposing (..)
import Array exposing (Array)
import Lens as L
arrayRecord : {foo : Array {bar : Int}}
arrayRecord =
{ foo =
Array.fromList [{ bar = 2 }, { bar = 3 }, {bar = 4}]
}
all (L.foo << every << L.bar) arrayRecord
--> [2, 3, 4]
map (L.foo << every << L.bar) ((+) 1) arrayRecord
--> {foo = Array.fromList [{bar = 3}, {bar = 4}, {bar = 5}]}This accessor lets you traverse an Array including the index of each element
alias for Array.Accessors.eachIdx
import Accessors exposing (..)
import Lens as L
import Array exposing (Array)
arrayRecord : { foo : Array { bar : Int } }
arrayRecord = { foo = [ {bar = 2}
, {bar = 3}
, {bar = 4}
] |> Array.fromList
}
multiplyIfGTOne : (Int, { bar : Int }) -> { bar : Int }
multiplyIfGTOne ( idx, ({ bar } as rec) ) =
if idx > 0 then
{ bar = bar * 10 }
else
rec
all (L.foo << everyIdx) arrayRecord
--> [(0, {bar = 2}), (1, {bar = 3}), (2, {bar = 4})]
map (L.foo << everyIdx) multiplyIfGTOne arrayRecord
--> {foo = [{bar = 2}, {bar = 30}, {bar = 40}] |> Array.fromList}
all (L.foo << everyIdx << ixd L.bar) arrayRecord
--> [2, 3, 4]
map (L.foo << everyIdx << ixd L.bar) ((+) 1) arrayRecord
--> {foo = [{bar = 3}, {bar = 4}, {bar = 5}] |> Array.fromList}alias for Array.Accessors.at
import Accessors exposing (..)
import Array exposing (Array)
import Lens as L
arr : Array { bar : String }
arr = Array.fromList [{ bar = "Stuff" }, { bar = "Things" }, { bar = "Woot" }]
try (ix 1) arr
--> Just { bar = "Things" }
try (ix 9000) arr
--> Nothing
try (ix 0 << L.bar) arr
--> Just "Stuff"
set (ix 0 << L.bar) "Whatever" arr
--> Array.fromList [{ bar = "Whatever" }, { bar = "Things" }, { bar = "Woot" }]
set (ix 9000 << L.bar) "Whatever" arr
--> arrLens over the first component of a Tuple
alias for Tuple.Accessors.fst
import Accessors exposing (..)
charging : (String, Int)
charging = ("It's over", 1)
get fst charging
--> "It's over"
set fst "It's over" charging
--> ("It's over", 1)
map fst (\s -> String.toUpper s ++ "!!!") charging
--> ("IT'S OVER!!!", 1)alias for Tuple.Accessors.snd
import Accessors exposing (..)
meh : (String, Int)
meh = ("It's over", 1)
get snd meh
--> 1
set snd 1125 meh
--> ("It's over", 1125)
meh
|> set snd 1125
|> map fst (\s -> String.toUpper s ++ "!!!")
|> map snd ((*) 8)
--> ("IT'S OVER!!!", 9000)
Any Optic is both "lens" and "prism".