lens-3.8.7.3: Lenses, Folds and Traversals

Portability | Rank2Types
Stability | provisional
Maintainer | Edward Kmett <ekmett@gmail.com>
Safe Haskell | Trustworthy

Control.Lens.Getter

Contents

- Getters
- Building Getters
- Combinators for Getters and Folds
- Indexed Getters
  - Indexed Getter Combinators
- Implementation Details

Description

A ``Getter` s a` is just any function `(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.

Synopsis

- 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 s

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 s

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 t

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 ``Getting` r s t a b`, then when `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 t

Used to consume an `IndexedFold`.

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

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 a

Build a `Getter` from an arbitrary Haskell function.

     to f . to g ≡ to (g . f)

     a ^. to f ≡ f a

    >>> a ^.to f
    f a

    >>> ("hello","world")^.to snd
    "world"

    >>> 5^.to succ
    6

    >>> (0, -5)^._2.to abs
    5

# Combinators for Getters and Folds

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

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

    >>> (a,b)^._2
    b

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

    >>> import Data.Complex
    >>> ((0, 1 :+ 2), 3)^._1._2.to magnitude
    2.23606797749979

     (^.) ::             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 a

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

    >>> view (to f) a
    f a

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

    >>> view (to succ) 5
    6

    >>> view (_2._1) ("hello",("world","!!!"))
    "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 r

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)

    >>> views (to f) g a
    g (f a)

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

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 a

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

    >>> view' (to f) a
    f a

    >>> view' _2 (1,"hello")
    "hello"

    >>> view' (to succ) 5
    6

    >>> view' (_2._1) ("hello",("world","!!!"))
    "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 r

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)

    >>> views' _2 length (1,"hello")
    5

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 a

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.

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

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

     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 r

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.

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

     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 a

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.

    >>> evalState (use' _1) (a,b)
    a

    >>> evalState (use' _1) ("hello","world")
    "hello"

     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 r

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.

    >>> evalState (uses' _1 length) ("hello","world")
    5

     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)

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)

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)

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

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

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

     (^@.) :: 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)

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 r

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)

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 r

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

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)

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.

     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 where

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 ``Gettable` f` an "anyvariant" `Functor`.

Methods

coerce :: f a -> f b

Replace the phantom type argument.

Instances

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

newtype Accessor r a

Used instead of `Const` to report

    No instance for (Settable Accessor)

when the user attempts to misuse a `Setter` as a `Getter`, rather than a monolithic unification error.

Constructors

Accessor |
Fields runAccessor :: r

Instances

Effective Identity r (Accessor r) |
Functor (Accessor r) |
Monoid r => Applicative (Accessor r) |
Semigroup r => Apply (Accessor r) |
Gettable (Accessor r) |