module Control.Monad.Trans.Cont (
Cont,
cont,
runCont,
mapCont,
withCont,
ContT(..),
mapContT,
withContT,
callCC,
liftLocal,
) where
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Data.Functor.Identity
import Control.Applicative
import Control.Monad
type Cont r = ContT r Identity
cont :: ((a -> r) -> r) -> Cont r a
cont f = ContT (\ k -> Identity (f (runIdentity . k)))
runCont :: Cont r a
-> (a -> r)
-> r
runCont m k = runIdentity (runContT m (Identity . k))
mapCont :: (r -> r) -> Cont r a -> Cont r a
mapCont f = mapContT (Identity . f . runIdentity)
withCont :: ((b -> r) -> (a -> r)) -> Cont r a -> Cont r b
withCont f = withContT ((Identity .) . f . (runIdentity .))
newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }
mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a
mapContT f m = ContT $ f . runContT m
withContT :: ((b -> m r) -> (a -> m r)) -> ContT r m a -> ContT r m b
withContT f m = ContT $ runContT m . f
instance Functor (ContT r m) where
fmap f m = ContT $ \c -> runContT m (c . f)
instance Applicative (ContT r m) where
pure a = ContT ($ a)
f <*> v = ContT $ \ k -> runContT f $ \ g -> runContT v (k . g)
instance Monad (ContT r m) where
return a = ContT ($ a)
m >>= k = ContT $ \c -> runContT m (\a -> runContT (k a) c)
instance MonadTrans (ContT r) where
lift m = ContT (m >>=)
instance (MonadIO m) => MonadIO (ContT r m) where
liftIO = lift . liftIO
callCC :: ((a -> ContT r m b) -> ContT r m a) -> ContT r m a
callCC f = ContT $ \c -> runContT (f (\a -> ContT $ \_ -> c a)) c
liftLocal :: Monad m => m r' -> ((r' -> r') -> m r -> m r) ->
(r' -> r') -> ContT r m a -> ContT r m a
liftLocal ask local f m = ContT $ \c -> do
r <- ask
local f (runContT m (local (const r) . c))