lens-family-core-2.1.2: Haskell 2022 Lens Families

Safe Haskell | Safe-Inferred
Language | Haskell2010

Lens.Family.Unchecked

Contents

- Adapters
- Lenses
- Traversals
- Prisms
- Grates
- Grids
- Documentation
- Types

Description

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 ``Either` a a` and `(`Bool`, a)` as follows:

    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

adapter Source #

Arguments

:: (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 Source #

Arguments

:: Functor f |
=> (s -> a) | getter
-> (s -> b -> t) | setter
-> LensLike f s t a b |

    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

prism Source #

Arguments

:: (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 Source #

Arguments

:: Functor g |
=> (((s -> a) -> b) -> t) | grater
-> GrateLike g s t a b |

    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 Source #

Arguments

:: Identical f |
=> ((a -> b) -> s -> t) | sec (semantic editor combinator)
-> LensLike f s t a b |

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

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

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 Source #

Arguments

:: Identical g |
=> ((a -> b) -> s -> t) | sec (semantic editor combinator)
-> GrateLike g s t a b |

`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 LensLike f s t a b = (a -> f b) -> s -> f t Source #

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

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

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

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

Minimal complete definition

extract

#### Instances

Instances details

Identical Identity Source # |
Instance details Defined in Lens.Family.Identical Methods extract :: Identity a -> a
Identical f => Identical (Backwards f) Source # |
Instance details Defined in Lens.Family.Identical Methods extract :: Backwards f a -> a
(Identical f, Identical g) => Identical (Compose f g) Source # |
Instance details Defined in Lens.Family.Identical Methods extract :: Compose f g a -> a