{- |
This module defines the @Accessor@ type.
It should be imported with qualification.
-}moduleData.Accessor.Basic(T,fromSetGet,fromLens,self,null,set,(^=),compose,get,(^.),modify,(^:),(.>),(<.),($%),)whereimportPreludehiding(null)-- * Define and construct accessors{- |
The access functions we propose, look very similar to those
needed for List.mapAccumL (but parameter order is swapped) and State monad.
They get the new value of the field and the record
and return the old value of the field and the record with the updated field.
-}newtypeTra=Cons{decons::a->r->(a,r)}fromSetGet::(a->r->r)->(r->a)->TrafromSetGetsetFgetF=Cons$\xr->(getFr,setFxr)fromLens::(r->(a,a->r))->TrafromLenslens=Cons$\xr->let(y,f)=lensrin(y,fx)-- Simple accessors{- |
Access the record itself
-}self::Trrself=fromSetGetconstid{- |
Access a (non-existing) element of type @()@
-}null::Tr()null=fromSetGet(flipconst)(const()){-
{- |
Access the result of a function.
Cf. "http://conal.net/blog/posts/semantic-editor-combinators/"
-}
result :: a -> T (a -> r) r
result = fromSetGet (flip const) (const ())
-}-- * Apply accessors, similar to State methods{- | Set the value of a field. -}set::Tra->a->r->rsetfx=snd.deconsfxinfixr5^=,^:infixl0$%{- |
'set' as infix operator.
This lets us write @first ^= 2+3 $ second ^= 5+7 $ record@.
-}(^=)::Tra->a->(r->r)(^=)=set{-
{- | Set many fields at once.
This function could also be used for initialisation of record,
if record value with undefined fields is provided.
Drawback:
Since all types in a list must have the same type,
you can set only values of the same type.
-}
setMany :: [r -> (a, r)] -> r -> r
setMany = flip (foldl (\x f -> snd (f x)))
-}{- |
This is a general function,
but it is especially useful for setting many values of different type at once.
-}compose::[r->r]->r->rcompose=flip(foldl(flipid)){- | Get the value of a field. -}get::Tra->r->agetf=fst.deconsfundefinedinfixl8^.{- |
'get' as infix operator.
This lets us write @record^.field^.subfield@.
This imitates Modula II syntax.
-}(^.)::r->Tra->a(^.)=flipget{- | Transform the value of a field by a function. -}modify::Tra->(a->a)->(r->r)modifyfgrOld=let(a,rNew)=deconsf(ga)rOldinrNew{- |
'modify' as infix operator.
This lets us write
@field^:subfield^:(2*) $ record@,
@record$%field^:subfield^:(2*)@
or @record$%field^:subfield^:(const 1)@.
-}(^:)::Tra->(a->a)->(r->r)(^:)=modify{- |
Flipped version of '($)'.
-}($%)::a->(a->b)->b($%)=flip($)-- * Accessor combinatorsinfixl9.>{- |
Accessor composition:
Combine an accessor with an accessor to a sub-field.
Speak \"stack\".
-}(.>)::Tab->Tbc->Tac(.>)fg=Cons$\cNewaOld->let(bOld,aNew)=deconsfbNewaOld(cOld,bNew)=deconsgcNewbOldin(cOld,aNew)infixr9<.{- |
Accessor composition the other direction.
> (<.) = flip (.>)
-}(<.)::Tbc->Tab->Tac(<.)=flip(.>)