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 Const to obtain:
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.
A common question is whether you can combine multiple Getters to
retrieve multiple values. Recall that all Getters are Folds and that
we have a Monoid m => Applicative (Const m) instance to play
with. Knowing this, we can use Data.Semigroup.<> to glue Folds
together:
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 Control.Lens.Fold.Fold,
since it just ignores the Applicative.
When you see this in a type signature it indicates that you can
pass the function a Lens, Getter,
Control.Lens.Traversal.Traversal, Control.Lens.Fold.Fold,
Control.Lens.Prism.Prism, Control.Lens.Iso.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
Control.Lens.Fold.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, Control.Lens.Traversal.Traversal and
Control.Lens.Iso.Iso we also restricted choices of the irrelevant t and
b parameters.
If a function accepts a Getting r s a, then when r is a Monoid, then
you can pass a Control.Lens.Fold.Fold (or
Control.Lens.Traversal.Traversal), otherwise you can only pass this a
Getter or Lens.
View the value pointed to by a Getter or Lens or the
result of folding over all the results of a Control.Lens.Fold.Fold or
Control.Lens.Traversal.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 (Prelude..).
(^.) :: s -> Getter s a -> a
(^.) :: Monoid m => s -> Control.Lens.Fold.Fold s m -> m
(^.) :: s -> Control.Lens.Iso.Iso' s a -> a
(^.) :: s -> Lens' s a -> a
(^.) :: Monoid m => s -> Control.Lens.Traversal.Traversal' s m -> m
View the value pointed to by a Getter, Control.Lens.Iso.Iso or
Lens or the result of folding over all the results of a
Fold or Control.Lens.Traversal.Traversal that points
at a monoidal value.
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 :: Control.Lens.Iso.Iso' s a -> s -> a
view :: Lens' s a -> s -> a
view :: Monoid m => Control.Lens.Traversal.Traversal' s m -> s -> m
In a more general setting, such as when working with a Monad transformer stack you can use:
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
Control.Lens.Traversal.Traversal.
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 :: Control.Lens.Iso.Iso' s a -> (a -> r) -> s -> r
views :: Lens' s a -> (a -> r) -> s -> r
views :: Monoid m => Control.Lens.Traversal.Traversal' s a -> (a -> m) -> s -> m
In a more general setting, such as when working with a Monad transformer stack you can use:
Use the target of a Lens, Control.Lens.Iso.Iso, or
Getter in the current state, or use a summary of a
Control.Lens.Fold.Fold or Control.Lens.Traversal.Traversal that points
to a monoidal value.
Use the target of a Lens, Control.Lens.Iso.Iso or
Getter in the current state, or use a summary of a
Control.Lens.Fold.Fold or Control.Lens.Traversal.Traversal that
points to a monoidal value.
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.
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.
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.
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.
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.
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.
Whereas in Haskell, one can think of a Functor as containing or producing
values, a contravariant functor is a functor that can be thought of as
consuming values.
As an example, consider the type of predicate functions a -> Bool. One
such predicate might be negative x = x < 0, which
classifies integers as to whether they are negative. However, given this
predicate, we can re-use it in other situations, providing we have a way to
map values to integers. For instance, we can use the negative predicate
on a person's bank balance to work out if they are currently overdrawn:
newtype Predicate a = Predicate { getPredicate :: a -> Bool }
instance Contravariant Predicate where
contramap :: (a' -> a) -> (Predicate a -> Predicate a')
contramap f (Predicate p) = Predicate (p . f)
| `- First, map the input...
`----- then apply the predicate.
overdrawn :: Predicate Person
overdrawn = contramap personBankBalance negative
Any instance should be subject to the following laws:
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.
Replace all locations in the output with the same value.
The default definition is contramap . const, but this may be
overridden with a more efficient version.
Because we ignore the second type parameter to Const,
the Applicative instance, which has
(<*>) :: Monoid m => Const m (a -> b) -> Const m a -> Const m b
essentially turns into Monoid m => m -> m -> m, which is (<>)