Safe Haskell | Safe |
---|---|

Language | Haskell98 |

*Caution*: Improper use of this module can lead to unexpected behaviour if the preconditions of the functions are not met.

## Synopsis

- adapter :: (Functor f, Functor g) => (s -> a) -> (b -> t) -> AdapterLike f g s t a b
- lens :: Functor f => (s -> a) -> (s -> b -> t) -> LensLike f s t a b
- prism :: (Applicative f, Traversable g) => (s -> Either t a) -> (b -> t) -> AdapterLike f g s t a b
- grate :: Functor g => (((s -> a) -> b) -> t) -> GrateLike g s t a b
- setting :: Identical f => ((a -> b) -> s -> t) -> LensLike f s t a b
- resetting :: Identical g => ((a -> b) -> s -> t) -> GrateLike g s t a b
- type AdapterLike f g s t a b = (g a -> f b) -> g s -> f t
- type AdapterLike' f g s a = (g a -> f a) -> g s -> f s
- type LensLike f s t a b = (a -> f b) -> s -> f t
- type LensLike' f s a = (a -> f a) -> s -> f s
- type GrateLike g s t a b = (g a -> b) -> g s -> t
- type GrateLike' g s a = (g a -> a) -> g s -> s
- class (Traversable f, Applicative f) => Identical f

# Adapters

An adapter represents a isomorphism between two types or a parametric isomorphism between two families of types.
For example we can build an adapter between the type families

and `Either`

a a`(`

as follows:`Bool`

, a)

timesTwo :: (Functor f, Functor g) => AdapterLike f g (Either a a) (Either b b) (Bool, a) (Bool b) timesTwo f x = fmap yang . f . fmap yin where yin (True, a) = Left a yin (False, a) = Right a yang (Left a) = (True, a) yang (Right a) = (False, a)

*Note*: It is possible to adapters without even depending on `lens-family-core`

by expanding away the type synonym.

timesTwo :: (Functor f, Functor g) => (g (Either a a) -> f (Either b b)) -> g (Bool, a) -> f (Bool, b)

The function `adapter`

can also be used to construct adapters from a pair of mutually inverse functions.

# Lenses

A lens focuses on a field of record type. Lenses can be used to get and/or set the focused field. How to create a lens family is best illustrated by the common example of a field of a record:

data MyRecord a = MyRecord { _myA :: a, _myInt :: Int } -- The use of type variables a and b allow for polymorphic updates. myA :: Functor f => LensLike f (MyRecord a) (MyRecord b) a b myA f (MyRecord a i) = (\b -> MyRecord b i) <$> f a -- The field _myInt is monomorphic, so we can use a 'LensLike'' type. -- However, the structure of the function is exactly the same as for LensLike. myInt :: Functor f => LensLike' f (MyRecord a) Int myInt f (MyRecord a i) = (\i' -> MyRecord a i') <$> f i

See the `lens-family-th`

package to generate this sort of code using Template Haskell.

*Note*: It is possible to build lenses without even depending on `lens-family-core`

by expanding away the type synonym.

myA :: Functor f => (a -> f b) -> (MyRecord a) -> f (MyRecord b)

You can build lenses for more than just fields of records.
Any value `l :: Functor f => LensLike f s t a b`

is well-defined when it satisfies the two van Laarhoven lens laws:

l Identity === Identity

l (Compose . fmap f . g) === Compose . fmap (l f) . (l g)

The function `lens`

can also be used to construct lenses.
The resulting lenses will be well-defined so long as their preconditions are satisfied.

# Traversals

If you have zero or more fields of the same type of a record, a traversal can be used to refer to all of them in order.
Multiple references are made by replacing the `Functor`

constraint of lenses with an `Applicative`

constraint.
Consider the following example of a record with two `Int`

fields.

data MyRecord = MyRecord { _myA :: Int, _myB :: Int, _myC :: Bool } -- myInts is a traversal over both fields of MyRecord. myInts :: Applicative f => LensLike' f MyRecord Int myInts f (MyRecord a b c) = MyRecord <$> f a <*> f b <*> pure c

If the record and the referenced fields are parametric, you can can build polymrphic traversals.
Consider the following example of a record with two `Maybe`

fields.

data MyRecord a = MyRecord { _myA0 :: Maybe a, _myA1 :: Maybe a, myC :: Bool } -- myMaybes is a traversal over both fields of MyRecord. myMaybes :: Applicative f => LensLike f (MyRecord a) (MyRecord b) (Maybe a) (Maybe b) myMaybes f (MyRecord a0 a1 c) = MyRecord <$> f a0 <*> f a1 <*> pure c

*Note*: It is possible to build traversals without even depending on `lens-family-core`

by expanding away the type synonym.

myMaybes :: Applicative f => (Maybe a -> f (Maybe b)) -> MyRecord a -> f (MyRecord b) myMaybes f (MyRecord a0 a1 c) = MyRecord <$> f a0 <*> f a1 <*> pure c

Unfortunately, there are no helper functions for making traversals. In most cases, you must make them by hand.

Any value `t :: Applicative f => LensLike f s t a b`

is well-defined when it satisfies the two van Laarhoven traversal laws:

t Identity === Identity

t (Compose . fmap f . g) === Compose . fmap (t f) . (t g)

`traverse`

is the canonical traversal for various containers.

# Prisms

A prism focuses on a single variant of a type.
They can be used to `matching`

/ `review`

the focused variant.
Consider the following example.

data MySum a = MyA a | MyB Int -- myA is a prism for the MyA variant of MySum myA :: (Applicative f, Traversable g) => AdapterLike f g (MySum a) (MySum b) a b myA f = either pure (fmap MyA . f) . traverse h where h (MyA a) = Right a h (MyB n) = Left (MyB n)

This prism can be used with `matching`

via `under`

:

`matching`

(`under`

myA) :: MySum a -> Either (MySum b) a

This prism can be used with `review`

via `over`

:

`review`

(`over`

myA) :: a -> MySum a

*Note*: It is possible to build prisms without even depending on `lens-family-core`

by expanding away the type synonym.

myA :: (Appicative f, Traversable g) => (g a -> f b) -> g (MySum a) -> f (MySum b)

You can build prism for more than just constructors of sum types.
Any value `p :: (Applicative f, Traversable g) => AdapterLike f g s t a b`

is well-defined when it satisfies the prism laws:

matching (under p) (review (over p) b) === Right b

(id ||| review (over p)) (matching (under p) s) === s

left (match (under p)) (matching (under p) s) === left Left (matching (under p) s)

The function `prism`

can also be used to construct prisms.
The resulting prisms will be well-defined so long as their preconditions are satisfied.

# Grates

A grate focuses on the contents of a representable functor.
In other words, a grate focuses on the codomain of a function type or something isomorphic to a function type.
They are used to lift operations on this codomain to operations on the larger structure via zipping.
Consider the following example of a stream of `Int`

s.

data IntStream = IntStream { hd :: Int, tl :: IntStream } -- myInts is a grate over the Ints of IntStream. myInts :: Functor g => GrateLike' g IntStream Int myInts f s = IntStream (f (hd <$> s)) (myInts f (tl <$> s))

If the contents are parametric, you can can build polymorphic grates. Consider the following example of a generic stream.

data Stream a = Stream { hd :: a, tl :: Stream a } -- myStream is a grate over the contents of a Stream. myStream :: Functor g => GrateLike g (Stream a) (Stream b) a b myStream f s = Stream (f (hd <$> s)) (myStream f (tl <$> s))

*Note*: It is possible to build grates without even depending on `lens-family-core`

by expanding away the type synonym.

myStream :: Functor g => (g (Stream a) -> Stream b) -> g a -> b

Any value `t :: Functor g => GrateLike g s t a b`

is a well-defined grate when it satisfies the two van Laarhoven traversal laws:

t runIdentity === runIdentity

t (f . fmap g . runCompose) === (t f) . fmap (t g) . runCompose

The function `grate`

can also be used to construct grates from graters.
The resulting grates will be well-defined so long as the preconditions are satisfied.

# Grids

A grid is both a traversal and a grate.
When you have a type that is isomorphic to a fixed and finite number of copies of another type, a grid can be used to zip or traverse them.
Consider the following example of a record with exactly two `Int`

fields.

data MyRecord = MyRecord { _myA :: Int, _myB :: Int } -- myInts is a grid over both fields of MyRecord. myInts :: (Applicative f, Functor g) => AdapterLike' f g MyRecord Int myInts f r = MyRecord <$> f (_myA <$> r) <*> f (_myB <$> r)

If the record and the referenced fields are parametric, you can can build polymorphic grids.
Consider the following example of a record with exactly two `Maybe`

fields.

data MyRecord a = MyRecord { _myA0 :: Maybe a, _myA1 :: Maybe a } -- myMaybes is a traversal over both fields of MyRecord. myMaybes :: (Applicative f, Functor g) => AdapterLike f g (MyRecord a) (MyRecord b) (Maybe a) (Maybe b) myMaybes f r = MyRecord <$> f (_myA0 <$> r) <*> f (_myA1 <$> r)

A grid is converted into a grate by using the `over`

function, and it is converted to a traversal by using the `under`

function.

*Note*: It is possible to build grids without even depending on `lens-family-core`

by expanding away the type synonym.

myMaybes :: (Applicative f, Functor g) => (g (Maybe a) -> f (Maybe b)) -> g (MyRecord a) -> f (MyRecord b)

Unfortunately, there are no helper functions for making grids. In most cases, you must make them by hand.

# Documentation

:: (Functor f, Functor g) | |

=> (s -> a) | yin |

-> (b -> t) | yang |

-> AdapterLike f g s t a b |

adapter :: (s -> a) -> (b -> t) -> Adapter s t a b

Build an adapter from an isomorphism family.

*Caution*: In order for the generated adapter family to be well-defined, you must ensure that the two isomorphism laws hold:

yin . yang === id

yang . yin === id

lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b

Build a lens from a `getter`

and `setter`

family.

*Caution*: In order for the generated lens family to be well-defined, you must ensure that the three lens laws hold:

getter (setter s a) === a

setter s (getter s) === s

setter (setter s a1) a2 === setter s a2

:: (Applicative f, Traversable g) | |

=> (s -> Either t a) | matcher |

-> (b -> t) | reviewer |

-> AdapterLike f g s t a b |

prism :: (s -> Either t a) -> (b -> t) -> Prism s t a b

Build a prism from a `matcher`

and `reviewer`

family.

*Caution*: In order for the generated prism family to be well-defined, you must ensure that the three prism laws hold:

matcher (reviewer b) === Right b

(id ||| reviewer) (matcher s) === s

left matcher (matcher s) === left Left (matcher s)

grate :: (((s -> a) -> b) -> t) -> Grate s t a b

Build a grate from a `grater`

family.

*Caution*: In order for the generated grate family to be well-defined, you must ensure that the two grater laws hold:

grater ($ s) === s

grater (k -> h (k . grater)) === grater (k -> h ($ k))

Note: The grater laws are that of an algebra for the parameterised continuation monad, `PCont`

.

`setting`

promotes a "semantic editor combinator" to a modify-only lens.
To demote a lens to a semantic edit combinator, use the section `(l %~)`

or `over l`

from Lens.Family.

`>>>`

[(3,0),(5,1),(5,1),(3,2)]`[("The",0),("quick",1),("brown",1),("fox",2)] & setting map . fstL %~ length`

*Caution*: In order for the generated family to be well-defined, you must ensure that the two functors laws hold:

sec id === id

sec f . sec g === sec (f . g)

`resetting`

promotes a "semantic editor combinator" to a form of grate that can only lift unary functions.
To demote a grate to a semantic edit combinator, use `under l`

from Lens.Family.

*Caution*: In order for the generated family to be well-defined, you must ensure that the two functors laws hold:

sec id === id

sec f . sec g === sec (f . g)

# Types

type AdapterLike f g s t a b = (g a -> f b) -> g s -> f t Source #

type AdapterLike' f g s a = (g a -> f a) -> g s -> f s Source #

type GrateLike' g s a = (g a -> a) -> g s -> s Source #

class (Traversable f, Applicative f) => Identical f Source #

extract