mini-0.1.0.0: Mini/Lens.hs
{-# LANGUAGE RankNTypes #-}
{- | Minimal library of /van Laarhoven/ lenses: composable polymorphic record
updates
-}
module Mini.Lens (
-- * Types
Lens,
-- * Construction
lens,
-- * Reading
view,
-- * Modifying
over,
-- * Writing
set,
) where
import Control.Applicative (
Const (
Const,
getConst
),
)
import Data.Functor.Identity (
Identity (
Identity,
runIdentity
),
)
{-
- Types
-}
{- | A purely functional reference for updating structures of type /s/ with
fields of type /a/ to structures of type /t/ with fields of type /b/
-}
type Lens s t a b = forall f. (Functor f) => (a -> f b) -> (s -> f t)
{-
- Construction
-}
{- | From a getter and a setter to a lens
> data Foo = Foo { _bar :: Bar } deriving Show
> data Bar = Bar { _baz :: Int } deriving Show
>
> bar :: Lens Foo Foo Bar Bar
> bar = lens _bar $ \s b -> s { _bar = b }
>
> baz :: Lens Bar Bar Int Int
> baz = lens _baz $ \s b -> s { _baz = b }
-}
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
lens sa sbt ab s = sbt s <$> ab (sa s)
{-
- Reading
-}
{- | From a lens and a structure to the value of the field of the structure
referenced by the lens
> ghci> view (bar . baz) $ Foo (Bar 73)
> 73
-}
view :: Lens s t a b -> s -> a
view o = getConst . o Const
{-
- Modifying
-}
{- | From a lens, an operation and a structure to the structure updated by
applying the operation to the value of the field referenced by the lens
> ghci> over (bar . baz) (+ 1) $ Foo (Bar 73)
> Foo {_bar = Bar {_baz = 74}}
-}
over :: Lens s t a b -> (a -> b) -> s -> t
over o ab = runIdentity . o (Identity . ab)
{-
- Writing
-}
{- | From a lens, a value and a structure to the structure updated by setting
the field referenced by the lens to the value
> ghci> set (bar . baz) 21 $ Foo (Bar 73)
> Foo {_bar = Bar {_baz = 21}}
-}
set :: Lens s t a b -> b -> s -> t
set o b = runIdentity . o (const $ Identity b)