lens: Lenses, Folds and Traversals
The combinators in Control.Lens
provide a highly generic toolbox for composing
families of getters, folds, traversals, setters and lenses.
Getter
A
is just any function Getter
a c(a -> c)
, which we've flipped into continuation
passing style, (c -> r) -> a -> r
and decorated with Const
to obtain
type Getting r a b c d = (c -> Const r d) -> a -> Const r b
If we restrict access to knowledge about the type r
and can work for any d and b, we get:
type Getter a c = forall r b d. Getting r a b c d
Everything you can do with a function, you can do with a Getter
, but note that because of the
continuation passing style (.) composes them in the opposite order.
Since it is only a function, every Getter
obviously only retrieves a single value for a given
input.
Fold
A
is a generalization of something Fold
a cFoldable
. It allows you to
extract multiple results from a container. A Foldable
container can be
characterized by the behavior of foldMap :: (Foldable t, Monoid m) => (c -> m) -> t c -> m
.
Since we want to be able to work with monomorphic containers, we generalize this signature to
forall m.
, and then decorate it with Monoid
m => (c -> m) -> a -> mConst
to obtain
type Fold a c = forall m b d. Monoid m => Getting m a b c d
Every Getter
is a valid Fold
that simply doesn't use the Monoid
it is passed.
Everything you can do with a Foldable
container, you can with with a Fold
and there are
combinators that generalize the usual Foldable
operations in Control.Lens
.
Traversal
A
is a generalization of Traversal
a b c dtraverse
from Traversable
. It allows
you to traverse over a structure and change out its contents with monadic or
applicative side-effects. Starting from
,
we monomorphize the contents and result to obtaintraverse
:: (Traversable
t, Applicative
f) => (c -> f d) -> t c -> f (t d)
type Traversal a b c d = forall f. Applicative f => (c -> f d) -> a -> f b
While a Traversal
isn't quite a Fold
, it _can_ be used for Getting
like a Fold
, because
given a Monoid
m
, we have an Applicative
for (
.Const
m)
Everything you can do with a Traversable
container, you can with with a Traversal
, and there
are combinators that generalize the usual Traversable
operations in Control.Lens
.
Setter
A
is a generalization of Setter
a b c dfmap
from Functor
. It allows you to map into a
structure and change out the contents, but it isn't strong enough to allow you to
enumerate those contents. Starting with fmap ::
we monomorphize the type to obtain Functor
f => (c -> d) -> f c -> f d(c -> d) -> a -> b
and then decorate it with Identity
to obtain
type Setter a b c d = (c -> Identity d) -> a -> Identity b
Every Traversal
is a valid Setter
, since Identity
is Applicative
.
Everything you can do with a Functor
, you can do with a Setter
, and there are combinators that
generalize the usual Functor
operations in Control.Lens
.
Lens
A
is a purely functional reference.Lens
a b c d
While a Traversal
could be used for Getting
like a valid Fold
, it wasn't a valid Getter
.
To make the Applicative
for Const
it required a Monoid
for the argument we passed it, which
a Getter
doesn't recieve.
However, the instance of Functor
for Const
requires no such thing. If we weaken the type
requirement from Applicative
to Functor
for Traversal
, we obtain
type Lens a b c d = forall f. Functor f => (c -> f d) -> a -> f b
Every Lens
is a valid Setter
, choosing f
= Identity
.
Every Lens
can be used for Getting
like a Fold
that doesn't use the Monoid
it is passed.
Every Lens
is a valid Traversal
that only uses the Functor
part of the Applicative
it is supplied.
Every Lens
can be used for Getting
like a valid Getter
, choosing f
= Const
r
for an appropriate r
Since every Lens
can be used for Getting
like a valid Getter
it follows that it must view exactly one
element in the structure.
The lens laws follow from this property and the desire for it to act like a Functor
when used as a Setter
.
Isomorphisms and Iso
Control.Isomorphic provides easy overloading of function application for isomorphisms and Iso a b c d
uses it
to form isomorphism families that can be composed with other isomorphisms and with lenses, setters, folds,
traversals and getters.
type Iso a b c d = forall k f. (Isomorphic k, Functor f) => k (c -> f d) (a -> f b)
Composition
Note that all of these types are type aliases, and you can compose these lenses with mere function compositon.
This is a generalization of the well-known trick for (.).(.)
or fmap.fmap
, and their less well-known cousins
foldMap.foldMap
traverse.traverse
. It follows because each one is a function between values of type (x -> f y)
and the composition takes the intersection of supplied functionality for you automatically!
Lens Families
For a longer description of why you should care about lenses, and an overview of why we use 4 parameters a, b, c, and d instead of just 2, see http://comonad.com/reader/2012/mirrored-lenses/.
Sometimes you won't need the flexibility those extra parameters afford you and you can use
type Simple f a b = f a a b b
to describe a Simple
Setter
, Simple
Traversal
, Simple
Lens
or Simple
Iso
.
Avoiding Dependencies
Note: If you merely want your library to provide lenses you may not
have to actually import any lens library at all. For, say, a
, just export a function with the signature:Simple
Lens
Bar Foo
foo :: Functor f => (Foo -> f Foo) -> Bar -> f Bar
and then you can compose it with other lenses using nothing more than (.)
from the Prelude.
Deriving Lenses
You can derive lenses automatically for many data types using Control.Lens.TH
, and if a
container is fully characterized by its lenses, you can use Control.Lens.Representable
to
automatically derive Functor
, Applicative
, Monad
, and Derivable
.
Modules
[Index]
- Control
- Data
- Array
- Bits
- ByteString
- Complex
- Dynamic
- Either
- IntMap
- IntSet
- List
- Map
- Pair
- Sequence
- Set
- Text
- Tree
- GHC
- Generics
- Language
- Haskell
Downloads
- lens-1.4.1.tar.gz [browse] (Cabal source package)
- Package description (as included in the package)
Maintainer's Corner
For package maintainers and hackage trustees
Candidates
- No Candidates
Versions [RSS] | 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.0.1, 1.0.2, 1.0.3, 1.1, 1.1.1, 1.2, 1.3, 1.3.1, 1.4, 1.4.1, 1.5, 1.6, 1.7, 1.7.1, 1.8, 1.9, 1.9.1, 2.0, 2.1, 2.2, 2.3, 2.4, 2.4.0.2, 2.5, 2.6, 2.6.1, 2.7, 2.7.0.1, 2.8, 2.9, 3.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.1, 3.2, 3.3, 3.4, 3.5, 3.5.1, 3.6, 3.6.0.1, 3.6.0.2, 3.6.0.3, 3.6.0.4, 3.7, 3.7.0.1, 3.7.0.2, 3.7.1, 3.7.1.1, 3.7.1.2, 3.7.2, 3.7.3, 3.7.4, 3.7.5, 3.7.6, 3.8, 3.8.0.1, 3.8.0.2, 3.8.1, 3.8.2, 3.8.3, 3.8.4, 3.8.5, 3.8.6, 3.8.7, 3.8.7.1, 3.8.7.2, 3.8.7.3, 3.9, 3.9.0.1, 3.9.0.2, 3.9.0.3, 3.9.1, 3.9.2, 3.10, 3.10.0.1, 3.10.1, 3.10.2, 3.10.3, 4.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.0.5, 4.0.6, 4.0.7, 4.1, 4.1.1, 4.1.2, 4.1.2.1, 4.2, 4.3, 4.3.1, 4.3.2, 4.3.3, 4.4, 4.4.0.1, 4.4.0.2, 4.5, 4.6, 4.6.0.1, 4.7, 4.7.0.1, 4.8, 4.9, 4.9.1, 4.10, 4.11, 4.11.1, 4.12, 4.12.1, 4.12.2, 4.12.3, 4.13, 4.13.1, 4.13.2, 4.13.2.1, 4.14, 4.15, 4.15.1, 4.15.2, 4.15.3, 4.15.4, 4.16, 4.16.1, 4.17, 4.17.1, 4.18, 4.18.1, 4.19, 4.19.1, 4.19.2, 5, 5.0.1, 5.1, 5.1.1, 5.2, 5.2.1, 5.2.2, 5.2.3, 5.3, 5.3.1, 5.3.2 |
---|---|
Dependencies | array (>=0.3.0.2 && <0.5), base (>=4.3 && <5), bytestring (>=0.9.1.10 && <0.10), containers (>=0.4.2 && <0.6), ghc-prim, mtl (>=2.0.1 && <2.2), parallel (>=3.1.0.1 && <3.3), template-haskell (>=2.4 && <2.8), text (>=0.11.1.5 && <0.12), transformers (>=0.2.2 && <0.4) [details] |
Tested with | ghc ==7.4.1 |
License | BSD-3-Clause |
Copyright | Copyright (C) 2012 Edward A. Kmett |
Author | Edward A. Kmett |
Maintainer | Edward A. Kmett <ekmett@gmail.com> |
Category | Data, Lenses |
Home page | http://github.com/ekmett/lens/ |
Bug tracker | http://github.com/ekmett/lens/issues |
Source repo | head: git clone git://github.com/ekmett/lens.git |
Uploaded | by EdwardKmett at 2012-08-03T17:10:35Z |
Distributions | Arch:5.2.3, Debian:4.18.1, Fedora:5.2.2, FreeBSD:4.12.3, LTSHaskell:5.2.3, NixOS:5.2.3, Stackage:5.3.2, openSUSE:5.2.3 |
Reverse Dependencies | 1438 direct, 6470 indirect [details] |
Downloads | 422834 total (752 in the last 30 days) |
Rating | 3.0 (votes: 50) [estimated by Bayesian average] |
Your Rating | |
Status | Docs uploaded by user Build status unknown [no reports yet] |