lens-family-core-1.2.0: Haskell 98 Lens Families

Safe HaskellSafe-Inferred
LanguageHaskell98

Lens.Family.Unchecked

Contents

Description

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

Synopsis

Lenses

A lens family is created by separating a substructure from the rest of its structure by a functor. 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, _myB :: Int }

-- The use of type variables a and a' allow for polymorphic updates.
myA :: Functor f => LensLike f (MyRecord a) (MyRecord a') a a'
myA f (MyRecord a b) = (\a' -> MyRecord a' b) `fmap` (f a)

-- The field _myB is monomorphic, so we can use a 'LensLike''  type.
-- However, the structure of the function is exactly the same as for LensLike.
myB :: Functor f => LensLike' f (MyRecord a) Int
myB f (MyRecord a b) = (\b' -> MyRecord a b') `fmap` (f b)

By following this template you can safely build your own lenses. To use this template, you do not need anything from this module other than the type synonyms LensLike and LensLike', and even they are optional. See the lens-family-th package to generate this code using Template Haskell.

Note: It is possible to build lenses without even depending on lens-family-core by expanding away the type synonym.

-- A lens definition that only requires the Haskell "Prelude".
myA :: Functor f => (a -> f a') -> (MyRecord a) -> f (MyRecord a')
myA f (MyRecord a b) = (\a' -> MyRecord a' b) `fmap` (f a)

You can build lenses for more than just fields of records. Any value l :: Functor f => LensLike f a a' b 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 functions lens and iso 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 }

-- myInts is a traversal over both fields of MyRecord.
myInts :: Applicative f => LensLike' f MyRecord Int
myInts f (MyRecord a b) = MyRecord <$> f a <*> f b

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

data MyRecord a = MyRecord { _myA :: Maybe a, _myB :: Maybe a }

-- myInts is a traversal over both fields of MyRecord.
myMaybes :: Applicative f => LensLike f (MyRecord a) (MyRecord a') (Maybe a) (Maybe a')
myMaybes f (MyRecord a b) = MyRecord <$> f a <*> f b

Note: As with lenses, is possible to build traversals without even depending on lens-family-core by expanding away the type synonym.

-- A traversal definition that only requires the Haskell "Prelude".
myMaybes :: Applicative f => (Maybe a -> f (Maybe a')) -> MyRecord a -> f (MyRecord a')
myMaybes f (MyRecord a b) = MyRecord <$> f a <*> f b

Unfortuantely, there are no helper functions for making traversals. You must make them by hand.

Any value t :: Applicative f => LensLike f a a' b 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.

Documentation

lens Source

Arguments

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

getter

-> (a -> b' -> a')

setter

-> LensLike f a a' b b' 
lens :: (a -> b) -> (a -> b' -> a') -> Lens a a' b b'

Build a lens from a getter and setter families.

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

  • getter (setter a b) === b
  • setter a (getter a) === a
  • setter (setter a b1) b2) === setter a b2

iso Source

Arguments

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

yin

-> (b' -> a')

yang

-> LensLike f a a' b b' 
iso :: (a -> b) -> (b' -> a') -> Lens a a' b b'

Build a lens from isomorphism families.

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

  • yin . yang === id
  • yang . yin === id

setting Source

Arguments

:: Identical f 
=> ((b -> b') -> a -> a')

sec (semantic editor combinator)

-> LensLike f a a' b 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.

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

Caution: In order for the generated setter 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 LensLike f a a' b b' = (b -> f b') -> a -> f a' Source

type LensLike' f a b = (b -> f b) -> a -> f a Source

class Applicative f => Identical f Source

Minimal complete definition

extract