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 a 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
- IntMap
- IntSet
- Map
- Sequence
- Set
- Text
- Time
- Calendar
- Tree
Downloads
- lens-1.2.tar.gz [browse] (Cabal source package)
- Package description (revised from the package)
Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.
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, 5.3.3, 5.3.4, 5.3.5 |
|---|---|
| Dependencies | array (>=0.4 && <0.5), base (>=4.5 && <5), bytestring (>=0.9 && <0.10), containers (>=0.3 && <0.6), mtl (>=2.1.1 && <2.2), parallel (>=3.2 && <3.3), template-haskell (>=2.4 && <2.8), text (>=0.11 && <0.12), time (>=1.4 && <1.5), transformers (>=0.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> |
| Revised | Revision 1 made by EdwardKmett at 2015-07-14T00:47:12Z |
| 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-07-31T22:26:43Z |
| Distributions | Arch:5.3.3, Debian:4.18.1, Fedora:5.3.4, FreeBSD:4.12.3, LTSHaskell:5.3.5, NixOS:5.3.4, Stackage:5.3.5, openSUSE:5.3.5 |
| Reverse Dependencies | 1483 direct, 6982 indirect [details] |
| Downloads | 429122 total (507 in the last 30 days) |
| Rating | 3.0 (votes: 51) [estimated by Bayesian average] |
| Your Rating | |
| Status | Docs uploaded by user Build status unknown [no reports yet] |