error-continuations-0.1.0.0: src/Control/Monad/EitherCont.hs
{-|
Module : Control.Monad.EitherCont
Description : The 'EitherCont' type and API
Copyright : (c) Eitan Chatav, 2015
License : PublicDomain
Maintainer : eitan.chatav@gmail.com
Stability : experimental
The 'EitherCont' type and API provide an idiomatic way to handle errors in
continuation passing style.
-}
module Control.Monad.EitherCont
( EitherCont
, EitherContT()
, eitherCont
, runEitherCont
, liftEither
, fmapL
, bimapEC
, throwEC
, apL
, catchEC
, liftL
, flipEC
, mapEitherCont
, withEitherContL
, withEitherContR
, callCCL
) where
import Control.Monad.Trans.EitherCont
import Data.Functor.Identity
-- |'EitherCont' 'a' 'l' 'r' is a CPS computation that produces an intermediate
-- result of type 'a' within a CPS computation which produces either a success
-- of type 'r' or failure of type 'l'.
type EitherCont a l r = EitherContT a l Identity r
-- |Construct a continuation-passing computation from a function.
eitherCont :: ((l -> a) -> (r -> a) -> a) -> EitherCont a l r
eitherCont ec = EitherContT $ \kl kr -> Identity $
ec (runIdentity . kl) (runIdentity . kr)
-- |The result of running a CPS computation with given failure and success
-- continuations.
--
-- prop> runEitherCont . eitherCont = id
-- prop> eitherCont . runEitherCont = id
runEitherCont :: EitherCont a l r -> (l -> a) -> (r -> a) -> a
runEitherCont ec kl kr = runIdentity $
runEitherContT ec (Identity . kl) (Identity . kr)
-- |'liftEither' embeds 'Either' in 'EitherCont' 'a'.
liftEither :: Either l r -> EitherCont a l r
liftEither e = eitherCont $ \kl kr -> either kl kr e
-- |Apply a function to transform the result of a continuation-passing
-- computation.
mapEitherCont :: (a -> a) -> EitherCont a l r -> EitherCont a l r
mapEitherCont = mapEitherContT . fmap
-- |Apply a function to transform the success continuation passed to a
-- continuation-passing computation.
withEitherContR :: ((r' -> a) -> r -> a)
-> EitherCont a l r
-> EitherCont a l r'
withEitherContR f = withEitherContTR ((Identity .) . f . (runIdentity .))
-- |Apply a function to transform the failure continuation passed to an
-- continuation-passing computation.
withEitherContL :: ((l' -> a) -> l -> a)
-> EitherCont a l r
-> EitherCont a l' r
withEitherContL f = withEitherContTL ((Identity .) . f . (runIdentity .))