error-continuations-0.1.0.0: src/Control/Monad/Trans/MaybeCont.hs
{-|
Module : Control.Monad.Trans.MaybeContT
Description : The 'MaybeContT' type and API
Copyright : (c) Eitan Chatav, 2015
License : PublicDomain
Maintainer : eitan.chatav@gmail.com
Stability : experimental
The 'MaybeContT' type and API provide an idiomatic way to handle possibly
failing computations in continuation passing style over some base monad.
-}
module Control.Monad.Trans.MaybeCont
( MaybeContT
( MaybeContT
, runMaybeContT
)
, liftMaybeT
, nothingC
, mapMaybeContT
, withMaybeContTJust
, withMaybeContTNothing
) where
import Control.Applicative
import Control.Monad.Cont
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
-- |The 'MaybeContT' 'a' 'l' 'm' 'r' type encodes a nullable monad transformer
-- in continuation passing style which is monadic in 'r'. This property holds
-- for any type constructor 'm'.
newtype MaybeContT a m r
-- |Construct a continuation-passing computation from a function.
= MaybeContT
{ -- |The result of running a CPS computation with given nothing and
-- just continuations.
runMaybeContT :: m a -> (r -> m a) -> m a
}
-- |'liftMaybeT' embeds 'MaybeT' in 'MaybeContT' 'a'.
liftMaybeT :: Monad m => MaybeT m r -> MaybeContT a m r
liftMaybeT may = MaybeContT $ \ma k -> maybe ma k =<< runMaybeT may
-- |The 'Functor' instance encodes functoriality of 'MaybeContT' 'a' 'm'.
instance Functor (MaybeContT a m) where
fmap f mc = MaybeContT $ \ma k -> runMaybeContT mc ma (k . f)
-- |The 'Applicative' instance encodes applicativity of 'MaybeContT' 'a' 'm'.
instance Applicative (MaybeContT a m) where
pure r = MaybeContT $ \_ k -> k r
mcf <*> mc = MaybeContT $ \ma k ->
runMaybeContT mcf ma (\f -> runMaybeContT mc ma (k . f))
-- |The 'Monad' instance encodes monadicity of 'MaybeContT' 'a' 'm'.
instance Monad (MaybeContT a m) where
return = pure
mc >>= mcf = MaybeContT $ \ma k ->
runMaybeContT mc ma (\r -> runMaybeContT (mcf r) ma k)
-- |'MaybeContT' 'a' is a monad transformer.
instance MonadTrans (MaybeContT a) where
lift mr = MaybeContT $ \_ k -> mr >>= k
-- |Call with current just continuation.
instance MonadCont (MaybeContT a m) where
callCC f = MaybeContT $ \ma k ->
runMaybeContT (f (\r -> (MaybeContT $ \_ _ -> k r))) ma k
-- |'nothingC' is the CPS representation of 'Nothing'.
nothingC :: MaybeContT a m r
nothingC = MaybeContT $ \ma _ -> ma
-- |Apply a function to transform the result of a continuation-passing
-- computation.
mapMaybeContT :: (m a -> m a) -> MaybeContT a m r -> MaybeContT a m r
mapMaybeContT f mc = MaybeContT $ \ma k -> f (runMaybeContT mc ma k)
-- |Apply a function to transform the just continuation passed to a
-- continuation-passing computation.
withMaybeContTJust :: ((r' -> m a) -> r -> m a)
-> MaybeContT a m r
-> MaybeContT a m r'
withMaybeContTJust f mc = MaybeContT $ \ma k -> runMaybeContT mc ma (f k)
-- |Apply a function to transform the nothing continuation passed to a
-- continuation-passing computation.
withMaybeContTNothing :: (m a -> m a) -> MaybeContT a m r -> MaybeContT a m r
withMaybeContTNothing f mc = MaybeContT $ \ma k -> runMaybeContT mc (f ma) k