Portability | Rank2Types |
---|---|

Stability | provisional |

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

Safe Haskell | Trustworthy |

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 `Accessor`

to obtain:

type`Getting`

r s t a b = (a ->`Accessor`

r b) -> s ->`Accessor`

r t

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

and can work for
any b and t, we could get:

type`Getter`

s a = forall r.`Getting`

r s s a a

But we actually hide the use of `Accessor`

behind a class `Gettable`

to 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. Gettable f => (a -> f a) -> s -> f s
- type IndexedGetter i s a = forall p f. (Indexable i p, Gettable f) => p a (f a) -> s -> f s
- type Getting r s t a b = (a -> Accessor r b) -> s -> Accessor r t
- type IndexedGetting i m s t a b = Indexed i a (Accessor m b) -> s -> Accessor m t
- type Accessing p m s t a b = p a (Accessor m b) -> s -> Accessor m t
- to :: (s -> a) -> IndexPreservingGetter s a
- (^.) :: s -> Getting a s t a b -> a
- view :: MonadReader s m => Getting a s t a b -> m a
- views :: (Profunctor p, MonadReader s m) => Overloading p (->) (Accessor r) s t a b -> p a r -> m r
- view' :: MonadReader s m => Getting a s s a a -> m a
- views' :: (Profunctor p, MonadReader s m) => Overloading' p (->) (Accessor r) s a -> p a r -> m r
- use :: MonadState s m => Getting a s t a b -> m a
- uses :: (Profunctor p, MonadState s m) => Overloading p (->) (Accessor r) s t a b -> p a r -> m r
- use' :: MonadState s m => Getting a s s a a -> m a
- uses' :: (Profunctor p, MonadState s m) => Overloading' p (->) (Accessor r) s a -> p a r -> m r
- listening :: MonadWriter w m => Getting u w t u b -> m a -> m (a, u)
- listenings :: MonadWriter w m => Getting v w t u b -> (u -> v) -> m a -> m (a, v)
- (^@.) :: s -> IndexedGetting i (i, a) s t a b -> (i, a)
- iview :: MonadReader s m => IndexedGetting i (i, a) s t a b -> m (i, a)
- iviews :: MonadReader s m => IndexedGetting i r s t a b -> (i -> a -> r) -> m r
- iuse :: MonadState s m => IndexedGetting i (i, a) s t a b -> m (i, a)
- iuses :: MonadState s m => IndexedGetting i r s t a b -> (i -> a -> r) -> m r
- ilistening :: MonadWriter w m => IndexedGetting i (i, u) w t u b -> m a -> m (a, (i, u))
- ilistenings :: MonadWriter w m => IndexedGetting i v w t u b -> (i -> u -> v) -> m a -> m (a, v)
- class Functor f => Gettable f where
- coerce :: f a -> f b

- newtype Accessor r a = Accessor {
- runAccessor :: r

# Getters

type Getter s a = forall f. Gettable f => (a -> f a) -> s -> f sSource

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 `(a -> s)`

.

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, Gettable f) => p a (f a) -> s -> f sSource

Every `IndexedGetter`

is a valid `IndexedFold`

and can be used for `Getting`

like a `Getter`

.

type Getting r s t a b = (a -> Accessor r b) -> s -> Accessor r tSource

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 t a b`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 t a b = Indexed i a (Accessor m b) -> s -> Accessor m tSource

Used to consume an `IndexedFold`

.

type Accessing p m s t a b = p a (Accessor m b) -> s -> Accessor m tSource

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

# Building Getters

to :: (s -> a) -> IndexPreservingGetter s aSource

# Combinators for Getters and Folds

(^.) :: s -> Getting a s t a b -> aSource

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 t a b -> m aSource

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) => Overloading p (->) (Accessor r) s t a b -> p a r -> m rSource

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 t a b -> (a -> r) -> m r

view' :: MonadReader s m => Getting a s s a a -> m aSource

This is a type restricted version of `view`

that expects a `Simple`

`Getter`

.

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 values.

`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) => Overloading' p (->) (Accessor r) s a -> p a r -> m rSource

This is a type restricted version of `views`

that expects a `Simple`

`Getter`

.

View the value of a `Getter`

, `Iso`

,
`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)

`>>>`

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:

`views'`

::`MonadReader`

s m =>`Getter`

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

:: (`MonadReader`

s m,`Monoid`

a) =>`Fold`

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

::`MonadReader`

s m =>`Iso'`

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

::`MonadReader`

s m =>`Lens'`

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

:: (`MonadReader`

s m,`Monoid`

a) =>`Traversal'`

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

`views'`

::`MonadReader`

s m =>`Getting`

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

use :: MonadState s m => Getting a s t a b -> m aSource

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) => Overloading p (->) (Accessor r) s t a b -> p a r -> m rSource

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

use' :: MonadState s m => Getting a s s a a -> m aSource

View the value of a `Getter`

, `Iso`

,

This is a type restricted version of `use`

that expects a `Simple`

`Getter`

.

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.

This use of this combinator may aid type-inference when working with lenses or traversals that have non-defaultable typeclass constraints on their arguments.

`>>>`

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) => Overloading' p (->) (Accessor r) s a -> p a r -> m rSource

This is a type restricted version of `uses`

that expects a `Simple`

`Getter`

.

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 s a a -> (a -> r) -> m r

listening :: MonadWriter w m => Getting u w t u b -> 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 t u b -> (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 t a b -> (i, a)Source

View the value pointed to by a `Getter`

or `Lens`

.

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 (`.`

).

`>>>`

(1,b)`(a,b,c,d)^@._2`

`>>>`

(1,"world")`("hello","world","!!!")^@._2`

(`^@.`

) :: 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 t a b -> 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 t a b -> (i -> a -> r) -> m rSource

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 t a b -> 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 t a b -> (i -> a -> r) -> m rSource

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 t u b -> 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 t u b -> (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 Functor f => Gettable f whereSource

Generalizing `Const`

so we can apply simple `Applicative`

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

A `Gettable`

`Functor`

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

To ensure this, an instance of `Gettable`

is required to satisfy:

`id`

=`fmap`

f =`coerce`

Which is equivalent to making a

an "anyvariant"
`Gettable`

f`Functor`

.

Gettable (Const r) | |

Gettable f => Gettable (Backwards f) | |

Gettable (Accessor r) | |

Gettable f => Gettable (Indexing64 f) | |

Gettable f => Gettable (Indexing f) | |

(Functor f, Gettable g) => Gettable (Compose f g) | |

Gettable (Effect m r) | |

(Profunctor p, Gettable g) => Gettable (PretextT p g a b) | |

(Profunctor p, Gettable g) => Gettable (BazaarT p g a b) | |

Gettable f => Gettable (TakingWhile p f a b) | |

Gettable (EffectRWS w st m s) |