data-accessor-0.1.2: src/Data/Accessor.hs
{- |
This module provides a simple abstract data type for
a piece of a data stucture that can be read from and
written to.
In contrast to "Data.Accessor.Basic" it is intended for unqualified import.
-}
module Data.Accessor
( Accessor, accessor,
setVal, (Accessor.^=), getVal, (Accessor.^.), (Accessor.^:),
getA, putA, (=:), (State.%=), modA, (State.%:),
(.>), (<.),
)
where
import qualified Data.Accessor.Basic as Accessor
import qualified Data.Accessor.MonadState as State
import Control.Monad.State (MonadState, )
-- |An @Accessor r a@ is an object that encodes how to
-- get and put a subject of type @a@ out of/into an object
-- of type @s@.
--
-- In order for an instance of this data structure @a@ to be
-- an 'Accessor', it must obey the following laws:
--
-- > getVal a (setVal a x r) = x
-- > setVal a (getVal a r) r = r
type Accessor r a = Accessor.T r a
-- |Construct an 'Accessor' from a @get@ and a @set@ method.
--
accessor ::
(r -> a) {- ^ get method -}
-> (a -> r -> r) {- ^ set method -}
-> Accessor r a
accessor = flip Accessor.fromSetGet
-- |Get a value from a record field that is specified by an Accessor
getVal ::
Accessor r a {- ^ record field -}
-> r {- ^ record -}
-> a {- ^ value of the field in the record -}
getVal = Accessor.get
-- |Set a value of a record field that is specified by an Accessor
setVal ::
Accessor r a {- ^ record field @f@ -}
-> a {- ^ value @x@ to be set -}
-> r {- ^ original record -}
-> r {- ^ new record with field @f@ changed to @x@ -}
setVal = Accessor.set
infixl 9 .>
{- |
Accessor composition:
Combine an accessor with an accessor to a sub-field.
Speak \"stack\".
-}
(.>) :: Accessor a b -> Accessor b c -> Accessor a c
(.>) = (Accessor..>)
infixr 9 <.
{- |
Accessor composition the other direction.
> (<.) = flip (.>)
-}
(<.) :: Accessor b c -> Accessor a b -> Accessor a c
(<.) = (Accessor.<.)
infix 1 =:
{- |
An \"assignment operator\" for state monads.
> (=:) = putA
-}
(=:) :: MonadState r m => Accessor r a -> a -> m ()
(=:) = putA
{-
infix 1 %=, %:
{- |
Another infix variant of 'putA'
that provides more consistency with the infix operators for records
(without State monad).
-}
(%=) :: MonadState r m => Accessor r a -> a -> m ()
(%=) = putA
{- |
Infix variant of 'modA'.
-}
(%:) :: MonadState r m => Accessor r a -> (a -> a) -> m ()
(%:) = modA
-}
-- |A structural dereference function for state monads.
getA :: MonadState r m => Accessor r a -> m a
getA = State.get
-- |A structural assignment function for state monads.
putA :: MonadState r m => Accessor r a -> a -> m ()
putA = State.set
-- |A structural modification function for state monads.
modA :: MonadState r m => Accessor r a -> (a -> a) -> m ()
modA = State.modify