Copyright | (C) 2012-14 Edward Kmett |
---|---|

License | BSD-style (see the file LICENSE) |

Maintainer | Edward Kmett <ekmett@gmail.com> |

Stability | provisional |

Portability | Rank2Types |

Safe Haskell | Trustworthy |

Language | Haskell98 |

A

is just any function `Getter`

s a`(s -> a)`

, which we've flipped
into continuation passing style, `(a -> r) -> s -> r`

and decorated
with `Const`

to obtain:

type`Getting`

r s a = (a ->`Const`

r a) -> s ->`Const`

r s

If we restrict access to knowledge about the type `r`

, we could get:

type`Getter`

s a = forall r.`Getting`

r s a

But we actually hide the use of `Const`

behind a class `Gettable`

to
report error messages from type class resolution rather than at unification
time, where they are much uglier.

type`Getter`

s a = forall f.`Gettable`

f => (a -> f a) -> s -> f s

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.

- type Getter s a = forall f. (Contravariant f, Functor f) => (a -> f a) -> s -> f s
- type IndexedGetter i s a = forall p f. (Indexable i p, Contravariant f, Functor f) => p a (f a) -> s -> f s
- type Getting r s a = (a -> Const r a) -> s -> Const r s
- type IndexedGetting i m s a = Indexed i a (Const m a) -> s -> Const m s
- type Accessing p m s a = p a (Const m a) -> s -> Const m s
- to :: (Profunctor p, Contravariant f) => (s -> a) -> Optical' p p f s a
- ito :: (Indexable i p, Contravariant f) => (s -> (i, a)) -> Optical' p (->) f s a
- (^.) :: s -> Getting a s a -> a
- view :: MonadReader s m => Getting a s a -> m a
- views :: (Profunctor p, MonadReader s m) => Optical p (->) (Const r) s s a a -> p a r -> m r
- use :: MonadState s m => Getting a s a -> m a
- uses :: (Profunctor p, MonadState s m) => Optical p (->) (Const r) s s a a -> p a r -> m r
- listening :: MonadWriter w m => Getting u w u -> m a -> m (a, u)
- listenings :: MonadWriter w m => Getting v w u -> (u -> v) -> m a -> m (a, v)
- (^@.) :: s -> IndexedGetting i (i, a) s a -> (i, a)
- iview :: MonadReader s m => IndexedGetting i (i, a) s a -> m (i, a)
- iviews :: MonadReader s m => IndexedGetting i r s a -> (i -> a -> r) -> m r
- iuse :: MonadState s m => IndexedGetting i (i, a) s a -> m (i, a)
- iuses :: MonadState s m => IndexedGetting i r s a -> (i -> a -> r) -> m r
- ilistening :: MonadWriter w m => IndexedGetting i (i, u) w u -> m a -> m (a, (i, u))
- ilistenings :: MonadWriter w m => IndexedGetting i v w u -> (i -> u -> v) -> m a -> m (a, v)
- class Contravariant f where
- coerce :: (Contravariant f, Functor f) => f a -> f b
- coerced :: (Functor f, Contravariant f) => LensLike f s t a b -> LensLike' f s a
- newtype Const a b :: * -> * -> * = Const {
- getConst :: a

- class (Contravariant f, Functor f) => Gettable f

# Getters

type Getter s a = forall f. (Contravariant f, Functor f) => (a -> f a) -> s -> f s Source

A `Getter`

describes how to retrieve a single value in a way that can be
composed with other `LensLike`

constructions.

Unlike a `Lens`

a `Getter`

is read-only. Since a `Getter`

cannot be used to write back there are no `Lens`

laws that can be applied to
it. In fact, it is isomorphic to an arbitrary function from `(s -> a)`

.

Moreover, a `Getter`

can be used directly as a `Fold`

,
since it just ignores the `Applicative`

.

type IndexedGetter i s a = forall p f. (Indexable i p, Contravariant f, Functor f) => p a (f a) -> s -> f s Source

Every `IndexedGetter`

is a valid `IndexedFold`

and can be used for `Getting`

like a `Getter`

.

type Getting r s a = (a -> Const r a) -> s -> Const r s Source

When you see this in a type signature it indicates that you can
pass the function a `Lens`

, `Getter`

,
`Traversal`

, `Fold`

,
`Prism`

, `Iso`

, or one of
the indexed variants, and it will just "do the right thing".

Most `Getter`

combinators are able to be used with both a `Getter`

or a
`Fold`

in limited situations, to do so, they need to be
monomorphic in what we are going to extract with `Const`

. To be compatible
with `Lens`

, `Traversal`

and
`Iso`

we also restricted choices of the irrelevant `t`

and
`b`

parameters.

If a function accepts a

, then when `Getting`

r s a`r`

is a `Monoid`

, then
you can pass a `Fold`

(or
`Traversal`

), otherwise you can only pass this a
`Getter`

or `Lens`

.

type IndexedGetting i m s a = Indexed i a (Const m a) -> s -> Const m s Source

Used to consume an `IndexedFold`

.

type Accessing p m s a = p a (Const m a) -> s -> Const m s Source

This is a convenient alias used when consuming (indexed) getters and (indexed) folds in a highly general fashion.

# Building Getters

to :: (Profunctor p, Contravariant f) => (s -> a) -> Optical' p p f s a Source

ito :: (Indexable i p, Contravariant f) => (s -> (i, a)) -> Optical' p (->) f s a Source

`ito`

:: (s -> (i, a)) ->`IndexedGetter`

i s a

# Combinators for Getters and Folds

(^.) :: s -> Getting a s a -> a infixl 8 Source

View the value pointed to by a `Getter`

or `Lens`

or the
result of folding over all the results of a `Fold`

or
`Traversal`

that points at a monoidal values.

This is the same operation as `view`

with the arguments flipped.

The fixity and semantics are such that subsequent field accesses can be
performed with (`.`

).

`>>>`

b`(a,b)^._2`

`>>>`

"world"`("hello","world")^._2`

`>>>`

`import Data.Complex`

`>>>`

2.23606797749979`((0, 1 :+ 2), 3)^._1._2.to magnitude`

(`^.`

) :: s ->`Getter`

s a -> a (`^.`

) ::`Monoid`

m => s ->`Fold`

s m -> m (`^.`

) :: s ->`Iso'`

s a -> a (`^.`

) :: s ->`Lens'`

s a -> a (`^.`

) ::`Monoid`

m => s ->`Traversal'`

s m -> m

view :: MonadReader s m => Getting a s a -> m a Source

View the value pointed to by a `Getter`

, `Iso`

or
`Lens`

or the result of folding over all the results of a
`Fold`

or `Traversal`

that points
at a monoidal value.

`view`

`.`

`to`

≡`id`

`>>>`

f a`view (to f) a`

`>>>`

"hello"`view _2 (1,"hello")`

`>>>`

6`view (to succ) 5`

`>>>`

"world"`view (_2._1) ("hello",("world","!!!"))`

As `view`

is commonly used to access the target of a `Getter`

or obtain a monoidal summary of the targets of a `Fold`

,
It may be useful to think of it as having one of these more restricted signatures:

`view`

::`Getter`

s a -> s -> a`view`

::`Monoid`

m =>`Fold`

s m -> s -> m`view`

::`Iso'`

s a -> s -> a`view`

::`Lens'`

s a -> s -> a`view`

::`Monoid`

m =>`Traversal'`

s m -> s -> m

In a more general setting, such as when working with a `Monad`

transformer stack you can use:

`view`

::`MonadReader`

s m =>`Getter`

s a -> m a`view`

:: (`MonadReader`

s m,`Monoid`

a) =>`Fold`

s a -> m a`view`

::`MonadReader`

s m =>`Iso'`

s a -> m a`view`

::`MonadReader`

s m =>`Lens'`

s a -> m a`view`

:: (`MonadReader`

s m,`Monoid`

a) =>`Traversal'`

s a -> m a

views :: (Profunctor p, MonadReader s m) => Optical p (->) (Const r) s s a a -> p a r -> m r Source

View a function of the value pointed to by a `Getter`

or `Lens`

or the result of
folding over the result of mapping the targets of a `Fold`

or
`Traversal`

.

`views`

l f ≡`view`

(l`.`

`to`

f)

`>>>`

g (f a)`views (to f) g a`

`>>>`

5`views _2 length (1,"hello")`

As `views`

is commonly used to access the target of a `Getter`

or obtain a monoidal summary of the targets of a `Fold`

,
It may be useful to think of it as having one of these more restricted signatures:

`views`

::`Getter`

s a -> (a -> r) -> s -> r`views`

::`Monoid`

m =>`Fold`

s a -> (a -> m) -> s -> m`views`

::`Iso'`

s a -> (a -> r) -> s -> r`views`

::`Lens'`

s a -> (a -> r) -> s -> r`views`

::`Monoid`

m =>`Traversal'`

s a -> (a -> m) -> s -> m

In a more general setting, such as when working with a `Monad`

transformer stack you can use:

`view`

::`MonadReader`

s m =>`Getter`

s a -> m a`view`

:: (`MonadReader`

s m,`Monoid`

a) =>`Fold`

s a -> m a`view`

::`MonadReader`

s m =>`Iso'`

s a -> m a`view`

::`MonadReader`

s m =>`Lens'`

s a -> m a`view`

:: (`MonadReader`

s m,`Monoid`

a) =>`Traversal'`

s a -> m a

`views`

::`MonadReader`

s m =>`Getting`

r s a -> (a -> r) -> m r

use :: MonadState s m => Getting a s a -> m a Source

Use the target of a `Lens`

, `Iso`

, or
`Getter`

in the current state, or use a summary of a
`Fold`

or `Traversal`

that points
to a monoidal value.

`>>>`

a`evalState (use _1) (a,b)`

`>>>`

"hello"`evalState (use _1) ("hello","world")`

`use`

::`MonadState`

s m =>`Getter`

s a -> m a`use`

:: (`MonadState`

s m,`Monoid`

r) =>`Fold`

s r -> m r`use`

::`MonadState`

s m =>`Iso'`

s a -> m a`use`

::`MonadState`

s m =>`Lens'`

s a -> m a`use`

:: (`MonadState`

s m,`Monoid`

r) =>`Traversal'`

s r -> m r

uses :: (Profunctor p, MonadState s m) => Optical p (->) (Const r) s s a a -> p a r -> m r Source

Use the target of a `Lens`

, `Iso`

or
`Getter`

in the current state, or use a summary of a
`Fold`

or `Traversal`

that
points to a monoidal value.

`>>>`

5`evalState (uses _1 length) ("hello","world")`

`uses`

::`MonadState`

s m =>`Getter`

s a -> (a -> r) -> m r`uses`

:: (`MonadState`

s m,`Monoid`

r) =>`Fold`

s a -> (a -> r) -> m r`uses`

::`MonadState`

s m =>`Lens'`

s a -> (a -> r) -> m r`uses`

::`MonadState`

s m =>`Iso'`

s a -> (a -> r) -> m r`uses`

:: (`MonadState`

s m,`Monoid`

r) =>`Traversal'`

s a -> (a -> r) -> m r

`uses`

::`MonadState`

s m =>`Getting`

r s t a b -> (a -> r) -> m r

listening :: MonadWriter w m => Getting u w u -> m a -> m (a, u) Source

This is a generalized form of `listen`

that only extracts the portion of
the log that is focused on by a `Getter`

. If given a `Fold`

or a `Traversal`

then a monoidal summary of the parts of the log that are visited will be
returned.

`listening`

::`MonadWriter`

w m =>`Getter`

w u -> m a -> m (a, u)`listening`

::`MonadWriter`

w m =>`Lens'`

w u -> m a -> m (a, u)`listening`

::`MonadWriter`

w m =>`Iso'`

w u -> m a -> m (a, u)`listening`

:: (`MonadWriter`

w m,`Monoid`

u) =>`Fold`

w u -> m a -> m (a, u)`listening`

:: (`MonadWriter`

w m,`Monoid`

u) =>`Traversal'`

w u -> m a -> m (a, u)`listening`

:: (`MonadWriter`

w m,`Monoid`

u) =>`Prism'`

w u -> m a -> m (a, u)

listenings :: MonadWriter w m => Getting v w u -> (u -> v) -> m a -> m (a, v) Source

This is a generalized form of `listen`

that only extracts the portion of
the log that is focused on by a `Getter`

. If given a `Fold`

or a `Traversal`

then a monoidal summary of the parts of the log that are visited will be
returned.

`listenings`

::`MonadWriter`

w m =>`Getter`

w u -> (u -> v) -> m a -> m (a, v)`listenings`

::`MonadWriter`

w m =>`Lens'`

w u -> (u -> v) -> m a -> m (a, v)`listenings`

::`MonadWriter`

w m =>`Iso'`

w u -> (u -> v) -> m a -> m (a, v)`listenings`

:: (`MonadWriter`

w m,`Monoid`

v) =>`Fold`

w u -> (u -> v) -> m a -> m (a, v)`listenings`

:: (`MonadWriter`

w m,`Monoid`

v) =>`Traversal'`

w u -> (u -> v) -> m a -> m (a, v)`listenings`

:: (`MonadWriter`

w m,`Monoid`

v) =>`Prism'`

w u -> (u -> v) -> m a -> m (a, v)

# Indexed Getters

## Indexed Getter Combinators

(^@.) :: s -> IndexedGetting i (i, a) s a -> (i, a) infixl 8 Source

View the index and value of an `IndexedGetter`

or `IndexedLens`

.

This is the same operation as `iview`

with the arguments flipped.

The fixity and semantics are such that subsequent field accesses can be
performed with (`.`

).

(`^@.`

) :: s ->`IndexedGetter`

i s a -> (i, a) (`^@.`

) :: s ->`IndexedLens'`

i s a -> (i, a)

The result probably doesn't have much meaning when applied to an `IndexedFold`

.

iview :: MonadReader s m => IndexedGetting i (i, a) s a -> m (i, a) Source

View the index and value of an `IndexedGetter`

into the current environment as a pair.

When applied to an `IndexedFold`

the result will most likely be a nonsensical monoidal summary of
the indices tupled with a monoidal summary of the values and probably not whatever it is you wanted.

iviews :: MonadReader s m => IndexedGetting i r s a -> (i -> a -> r) -> m r Source

View a function of the index and value of an `IndexedGetter`

into the current environment.

When applied to an `IndexedFold`

the result will be a monoidal summary instead of a single answer.

`iviews`

≡`ifoldMapOf`

iuse :: MonadState s m => IndexedGetting i (i, a) s a -> m (i, a) Source

Use the index and value of an `IndexedGetter`

into the current state as a pair.

When applied to an `IndexedFold`

the result will most likely be a nonsensical monoidal summary of
the indices tupled with a monoidal summary of the values and probably not whatever it is you wanted.

iuses :: MonadState s m => IndexedGetting i r s a -> (i -> a -> r) -> m r Source

Use a function of the index and value of an `IndexedGetter`

into the current state.

When applied to an `IndexedFold`

the result will be a monoidal summary instead of a single answer.

ilistening :: MonadWriter w m => IndexedGetting i (i, u) w u -> m a -> m (a, (i, u)) Source

This is a generalized form of `listen`

that only extracts the portion of
the log that is focused on by a `Getter`

. If given a `Fold`

or a `Traversal`

then a monoidal summary of the parts of the log that are visited will be
returned.

`ilistening`

::`MonadWriter`

w m =>`IndexedGetter`

i w u -> m a -> m (a, (i, u))`ilistening`

::`MonadWriter`

w m =>`IndexedLens'`

i w u -> m a -> m (a, (i, u))`ilistening`

:: (`MonadWriter`

w m,`Monoid`

u) =>`IndexedFold`

i w u -> m a -> m (a, (i, u))`ilistening`

:: (`MonadWriter`

w m,`Monoid`

u) =>`IndexedTraversal'`

i w u -> m a -> m (a, (i, u))

ilistenings :: MonadWriter w m => IndexedGetting i v w u -> (i -> u -> v) -> m a -> m (a, v) Source

`listen`

that only extracts the portion of
the log that is focused on by a `Getter`

. If given a `Fold`

or a `Traversal`

then a monoidal summary of the parts of the log that are visited will be
returned.

`ilistenings`

::`MonadWriter`

w m =>`IndexedGetter`

w u -> (i -> u -> v) -> m a -> m (a, v)`ilistenings`

::`MonadWriter`

w m =>`IndexedLens'`

w u -> (i -> u -> v) -> m a -> m (a, v)`ilistenings`

:: (`MonadWriter`

w m,`Monoid`

v) =>`IndexedFold`

w u -> (i -> u -> v) -> m a -> m (a, v)`ilistenings`

:: (`MonadWriter`

w m,`Monoid`

v) =>`IndexedTraversal'`

w u -> (i -> u -> v) -> m a -> m (a, v)

# Implementation Details

class Contravariant f where

Any instance should be subject to the following laws:

contramap id = id contramap f . contramap g = contramap (g . f)

Note, that the second law follows from the free theorem of the type of
`contramap`

and the first law, so you need only check that the former
condition holds.

coerce :: (Contravariant f, Functor f) => f a -> f b Source

This Generalizes `Const`

so we can apply simple `Applicative`

transformations to it and so we can get nicer error messages.

A `Functor`

you can `coerce`

ignores its argument, which it carries solely as a
phantom type parameter.

By the `Functor`

and `Contravariant`

laws, an instance of `Gettable`

will necessarily satisfy:

`id`

=`fmap`

f =`coerce`

=`contramap`

g

newtype Const a b :: * -> * -> *

Bitraversable Const | |

Bifunctor Const | |

Bifoldable Const | |

Effective Identity r (Const r) | |

Functor (Const m) | |

Monoid m => Applicative (Const m) | |

Foldable (Const m) | |

Traversable (Const m) | |

Generic1 (Const a) | |

Contravariant (Const a) | |

Semigroup m => Apply (Const m) | |

Generic (Const a b) | |

Monoid a => Monoid (Const a b) | |

Semigroup a => Semigroup (Const a b) | |

Wrapped (Const a x) | |

(~) * t (Const a' x') => Rewrapped (Const a x) t | |

type Rep1 (Const a) = D1 D1Const (C1 C1_0Const (S1 S1_0_0Const (Rec0 a))) | |

type Rep (Const a b) = D1 D1Const (C1 C1_0Const (S1 S1_0_0Const (Rec0 a))) | |

type Unwrapped (Const a x) = a |

class (Contravariant f, Functor f) => Gettable f Source

This class is provided mostly for backwards compatibility with lens 3.8, but it can also shorten type signatures.

(Contravariant f, Functor f) => Gettable f |