packages feed

cps-except-0.0.1.0: src/Control/Monad/CPSExcept.hs

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Control.Monad.CPSExcept where
import Control.Monad.Except
import Control.Monad.State
import Control.Monad.Reader()
import Control.Monad.Writer()
import Control.Monad.RWS()

newtype CPSExceptT e m a =
  CPSExceptT { getCPSExceptT :: forall r. ((e -> m r) -> (a -> m r) -> m r) }

runCPSExceptT :: Applicative m => CPSExceptT e m a -> m (Either e a)
runCPSExceptT (CPSExceptT f) = f (pure . Left)  (pure . Right)
{-# INLINE runCPSExceptT #-}

instance Functor (CPSExceptT e m) where
  fmap f (CPSExceptT g) = CPSExceptT $ \failC successC ->
    g failC (successC . f)
  {-# INLINE fmap #-}

instance Monad m => Applicative (CPSExceptT e m) where
  pure x = CPSExceptT $ \_failC successC -> successC x
  {-# INLINE pure #-}
  (<*>) = ap
  {-# INLINE (<*>) #-}

instance Monad m => Monad (CPSExceptT e m) where
  CPSExceptT f >>= g = CPSExceptT $ \failC successC ->
    f failC (\a -> getCPSExceptT (g a) failC successC)
  {-# INLINE (>>=) #-}

instance Monad m => MonadError e (CPSExceptT e m) where
  throwError e = CPSExceptT $ \failC _successC -> failC e
  {-# INLINE throwError #-}
  catchError (CPSExceptT f) handler =
    CPSExceptT $ \failC successC ->
    f (\e -> getCPSExceptT (handler e) failC successC)
    successC
  {-# INLINE catchError #-}

instance MonadTrans (CPSExceptT e) where
  lift m = CPSExceptT $ \_failC successC -> m >>= successC
  {-# INLINE lift #-}

instance MonadState s m => MonadState s (CPSExceptT e m) where
  state f = lift $ state f
  {-# INLINE state #-}