{-| 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