This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
Accessors, a library implementing lenses for Elm.
version 2.0.0
license BSD-3-Clause
native-modules False
elm-version 0.18.0 <= v < 0.19.0
Tag 2.0.1
Committed At 2019-05-16 09:44:37 UTC
elm-lang/core 5.1.1 <= v < 6.0.0 5.1.1

README

The Accessors library

This library provides a way to describe relations between a container and its content, and use that description to manipulate arbitrary data more easily.

Build your relations

There are two kinds of relations between a container and its content: 1:1 relations (e.g. a record and its field) and 1:n relations (e.g. a List can contain 0-n elements, a Maybe can contain 0-1 elements).

For 1:1 relations, the makeOneToOne function will let you build an accessor by describing how to get the sub-element from the super-element, and how to map a function over it. For instance, with a record:

recordFoo =
  makeOneToOne
    .foo
    (\change record -> {record | foo = change record.foo})

recordBar =
  makeOneToOne
    .bar
    (\change record -> {record | bar = change record.bar})

1:n relations are more complex in terms of abstraction, but they are usually very easy to implement:

onEach = 
  makeOneToN
    List.map
    List.map

try = 
  makeOneToN
    Maybe.map
    Maybe.map

Combine your relations

Accessors can be composed easily to describe relations:

myData = {foo = [ {bar = 3}
                , {bar = 2}
                , {bar = 0}
                ]
         }

myAccessor = recordFoo << onEach << recordBar

Manipulate your data easily

Then you use an action function to determine which kind of operation you want to do on your data using the accessor

getter   = get  myAccessor myData
  -- returns [3, 2, 0]

setter   = set  myAccessor 2 myData
  -- returns {foo = [{bar = 2}, {bar = 2}, {bar = 2}] }

transform = over myAccessor (\n -> n*2) myData
  -- returns {foo = [{bar = 6}, {bar = 4}, {bar = 0}] }

Type-safe and reusable

Applying an accessor on non-matching data structures will yield nice compile-time errors:

fail = (recordFoo << recordFoo) myData

--The 2nd argument to `get` is not what I expect:
--
--293| fail = get (recordFoo << recordFoo) myData
--                                         ^^^^^^
--This `myData` value is a:
--
--    { foo : List { bar : number } }
--
--But `get` needs the 2nd argument to be:
--
--    { foo : { a | foo : c } }

Any accessor you make can be composed with any other accessor to match your new data structures:

myOtherData = { bar = Just [1, 3, 2] }

halfWay = try << onEach
myOtherAccessor = recordBar << halfWay

getter = get  myOtherAccessor myOtherData
  -- returns Just [1, 3, 2]

Play with it in Ellie

Ellie default code with accessors.

Contribute

build

elm make

run tests (using 0.18 for now)

elm-test

If you write new accessor combinators that rely on common library datas, I'll be happy to review and merge. Please include tests for your combinators.