module Algebra.Monad.Cont (
MonadCont(..),
ContT(..),Cont,
contT, cont
) where
import Algebra.Monad.Base
newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }
deriving (Semigroup,Monoid,Semiring,Ring)
type Cont r a = ContT r Id a
instance Unit m => Unit (ContT r m) where pure a = ContT ($a)
instance Functor f => Functor (ContT r f) where
map f (ContT c) = ContT (\kb -> c (kb . f))
instance Applicative m => Applicative (ContT r m) where
ContT cf <*> ContT ca = ContT (\kb -> cf (\f -> ca (\a -> kb (f a))))
instance Monad m => Monad (ContT r m) where
ContT k >>= f = ContT (\cc -> k (\a -> runContT (f a) cc))
instance MonadTrans (ContT r) where
lift m = ContT (m >>=)
instance Monad m => MonadCont (ContT r m) where
callCC f = ContT (\k -> runContT (f (\a -> ContT (\_ -> k a))) k)
contT :: (Monad m,Unit m') => Iso (ContT r m r) (ContT r' m' r') (m r) (m' r')
contT = iso (\m -> ContT (m >>=)) (\c -> runContT c return)
cont :: Iso (Cont r r) (Cont r' r') r r'
cont = i'Id.contT