lens-1.5: Lenses, Folds and Traversals

PortabilityRank2Types
Stabilityprovisional
MaintainerEdward Kmett <ekmett@gmail.com>
Safe HaskellSafe-Infered

Control.Lens.Type

Contents

Description

A Lens a b c d is a purely functional reference.

While a Traversal could be used for Getting like a valid Fold, it wasn't a valid Getter as Applicative isn't a superclass of Gettable.

Functor, however is the superclass of both.

 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.

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 = Accessor 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 Traversable when used as a Traversal.

Synopsis

Lenses

type Lens a b c d = forall f. Functor f => (c -> f d) -> a -> f bSource

A Lens is actually a lens family as described in http://comonad.com/reader/2012/mirrored-lenses/.

With great power comes great responsibility and a Lens is subject to the three common sense lens laws:

1) You get back what you put in:

 view l (set l b a)  = b

2) Putting back what you got doesn't change anything:

 set l (view l a) a  = a

3) Setting twice is the same as setting once:

 set l c (set l b a) = set l c a

These laws are strong enough that the 4 type parameters of a Lens cannot vary fully independently. For more on how they interact, read the Why is it a Lens Family? section of http://comonad.com/reader/2012/mirrored-lenses/.

Every Lens can be used directly as a Setter or Traversal.

You can also use a Lens for Getting as if it were a Fold or Getter.

Since every lens is a valid Traversal, the traversal laws should also apply to any lenses you create.

  1. ) Idiomatic naturality:
 l pure = pure
  1. ) Sequential composition:
 fmap (l f) . l g = getCompose . l (Compose . fmap f . g)
 type Lens = forall f. Functor f => LensLike f a b c d

type Simple f a b = f a a b bSource

A Simple Lens, Simple Traversal, ... can be used instead of a Lens,Traversal, ... whenever the type variables don't change upon setting a value.

 imaginary :: Simple Lens (Complex a) a
 traverseHead :: Simple Traversal [a] a

Note: To use this alias in your own code with LensLike f or Setter, you may have to turn on LiberalTypeSynonyms.

lens :: (a -> c) -> (a -> d -> b) -> Lens a b c dSource

Build a Lens from a getter and a setter.

 lens :: Functor f => (a -> c) -> (a -> d -> b) -> (c -> f d) -> a -> f b

(%%~) :: LensLike f a b c d -> (c -> f d) -> a -> f bSource

(%%~) can be used in one of two scenarios:

When applied to a Lens, it can edit the target of the Lens in a structure, extracting a functorial result.

When applied to a Traversal, it can edit the targets of the Traversals, extracting an applicative summary of its actions.

For all that the definition of this combinator is just:

 (%%~) = id
 (%%~) :: Functor f =>     Iso a b c d       -> (c -> f d) -> a -> f b
 (%%~) :: Functor f =>     Lens a b c d      -> (c -> f d) -> a -> f b
 (%%~) :: Applicative f => Traversal a b c d -> (c -> f d) -> a -> f b

It may be beneficial to think about it as if it had these even more restrictive types, however:

When applied to a Traversal, it can edit the targets of the Traversals, extracting a supplemental monoidal summary of its actions, by choosing f = ((,) m)

 (%%~) ::             Iso a b c d       -> (c -> (e, d)) -> a -> (e, b)
 (%%~) ::             Lens a b c d      -> (c -> (e, d)) -> a -> (e, b)
 (%%~) :: Monoid m => Traversal a b c d -> (c -> (m, d)) -> a -> (m, b)

(%%=) :: MonadState a m => LensLike ((,) e) a a c d -> (c -> (e, d)) -> m eSource

Modify the target of a Lens in the current state returning some extra information of c or modify all targets of a Traversal in the current state, extracting extra information of type c and return a monoidal summary of the changes.

 (%%=) = (state.)

It may be useful to think of (%%=), instead, as having either of the following more restricted type signatures:

 (%%=) :: MonadState a m             => Iso a a c d       -> (c -> (e, d) -> m e
 (%%=) :: MonadState a m             => Lens a a c d      -> (c -> (e, d) -> m e
 (%%=) :: (MonadState a m, Monoid e) => Traversal a a c d -> (c -> (e, d) -> m e

Common Lenses

_1 :: Lens (a, c) (b, c) a bSource

This is a lens that can change the value (and type) of the first field of a pair.

 ghci> (1,2)^._1
 1
 ghci> _1 +~ "hello" $ (1,2)
 ("hello",2)
 _1 :: Functor f => (a -> f b) -> (a,c) -> f (a,c)

_2 :: Lens (c, a) (c, b) a bSource

As _1, but for the second field of a pair.

 anyOf _2 :: (c -> Bool) -> (a, c) -> Bool
 traverse._2 :: (Applicative f, Traversable t) => (a -> f b) -> t (c, a) -> f (t (c, b))
 foldMapOf (traverse._2) :: (Traversable t, Monoid m) => (c -> m) -> t (b, c) -> m
 _2 :: Functor f => (a -> f b) -> (c,a) -> f (c,b)

resultAt :: Eq e => e -> Simple Lens (e -> a) aSource

This lens can be used to change the result of a function but only where the arguments match the key given.

Traversing and Lensing

class Focus st whereSource

This class allows us to use focus on a number of different monad transformers.

Methods

focus :: Monad m => LensLike (Focusing m c) a a b b -> st b m c -> st a m cSource

Run a monadic action in a larger context than it was defined in, using a Simple Lens or Simple Traversal.

This is commonly used to lift actions in a simpler state monad into a state monad with a larger state type.

When applied to a 'Simple Traversal over multiple values, the actions for each target are executed sequentially and the results are aggregated monoidally and a monoidal summary of the result is given.

 focus :: Monad m             => Simple Iso a b       -> st b m c -> st a m c
 focus :: Monad m             => Simple Lens a b      -> st b m c -> st a m c
 focus :: (Monad m, Monoid c) => Simple Traversal a b -> st b m c -> st a m c

focus_ :: Monad m => LensLike (Focusing m ()) a a b b -> st b m c -> st a m ()Source

Like focus, but discarding any accumulated results as you go.

 focus_ :: Monad m             => Simple Iso a b       -> st b m c -> st a m ()
 focus_ :: Monad m             => Simple Lens a b      -> st b m c -> st a m ()
 focus_ :: (Monad m, Monoid c) => Simple Traversal a b -> st b m c -> st a m ()

setFocus :: Simple Setter a b -> st b Identity c -> st a Identity ()Source

A much more limited version of focus that can work with a Setter.

Cloning Lenses

clone :: Functor f => LensLike (IndexedStore c d) a b c d -> (c -> f d) -> a -> f bSource

Cloning a Lens is one way to make sure you arent given something weaker, such as a Traversal and can be used as a way to pass around lenses that have to be monomorphic in f.

Note: This only accepts a proper Lens, because IndexedStore lacks its (admissable) Applicative instance.

merged :: Functor f => LensLike f a b c c -> LensLike f a' b' c c -> LensLike f (Either a a') (Either b b') c cSource

Merge two lenses, getters, setters, folds or traversals.

bothLenses :: Lens a b c d -> Lens a' b' c' d' -> Lens (a, a') (b, b') (c, c') (d, d')Source

bothLenses makes a lens from two other lenses (or isomorphisms)

Simplified and In-Progress

type LensLike f a b c d = (c -> f d) -> a -> f bSource

Many combinators that accept a Lens can also accept a Traversal in limited situations.

They do so by specializing the type of Functor that they require of the caller.

If a function accepts a LensLike f a b c d for some Functor f, then they may be passed a Lens.

Further, if f is an Applicative, they may also be passed a Traversal.

type Overloaded k f a b c d = k (c -> f d) (a -> f b)Source

 type LensLike f a b c d = Overloaded (->) f a b c d

type SimpleLens a b = Lens a a b bSource

 type SimpleLens = Simple Lens

type SimpleLensLike f a b = LensLike f a a b bSource

 type SimpleLensLike f = Simple (LensLike f)

type SimpleOverloaded k f a b = Overloaded k f a a b bSource

 type SimpleOverloaded k f a b = Simple (Overloaded k f) a b