packages feed

ddc-code-0.4.3.1: tetra/base/Class/Applicative.ds

module Class.Applicative
export  
{       dFunctorOfApplicative;
        pure; ap;
        liftA; liftA2; liftA3
}
import Class.Functor
where


-- A functor with application.
data Applicative (f: Data -> Data) where
        Applicative
         :  Functor f 
         -> ([a: Data].   a -> f a)                     -- pure
         -> ([a b: Data]. f (a -> b) -> f a -> f b)     -- ap
         -> Applicative f


-- | Take the Functor dictionary from an Applicative dictionary.
dFunctorOfApplicative 
        : [f: Data -> Data]
        . Applicative f -> Functor f

dFunctorOfApplicative (Applicative dFunctor _ _)
 = dFunctor


-- | Return a value in the carrier.
pure    : [f: Data -> Data]. [a: Data]
        . Applicative f -> a -> f a

pure    (Applicative _ pure' _) x
 = pure' x


-- | Apply a function in the carrier its argument in another carrier.
ap      : [f: Data -> Data]. [a b: Data]
        . Applicative f -> f (a -> b) -> f a -> f b

ap      (Applicative _ _ ap') xfab xfa
 = ap' xfab xfa


-- Lifting functions.
liftA   (dapp: Applicative f) (f: a -> b) (xa: f a): f b
 = ap dapp (pure dapp f) xa


liftA2  (dapp: Applicative f)
        (f: a -> b -> c) (xa: f a) (xb: f b): f c
 = let  dfun    = dFunctorOfApplicative dapp
   in   ap dapp (fmap dfun f xa) xb


liftA3  (dapp: Applicative f) 
        (f: a -> b -> c -> d) (xa: f a) (xb: f b) (xc: f c): f d
 = let  dfun    = dFunctorOfApplicative dapp
   in   ap dapp (ap dapp (fmap dfun f xa) xb) xc