{-# LANGUAGE ScopedTypeVariables #-}
module Control.Monatron.Transformer (
StateT, stateT, runStateT,
WriterT, writerT, runWriterT,
ReaderT, readerT, runReaderT,
ExcT, excT, runExcT,
ContT, contT, runContT,
StepT, stepT, runStepT, caseStepT, unfoldStepT,
ListT, listT, runListT, foldListT, collectListT, emptyL, appendL,
module Control.Monatron.MonadT,
module Data.Monoid
) where
import Control.Monad.Fix
import Control.Monatron.MonadT
import Data.Monoid hiding ((<>))
import Control.Monatron.AutoInstances()
newtype StateT s m a = S { unS :: s -> m (a,s) }
stateT :: (s -> m (a, s)) -> StateT s m a
stateT = S
runStateT :: s -> StateT s m a -> m (a,s)
runStateT s m = unS m s
instance MonadT (StateT s) where
lift m = S $ \s -> m >>= \a -> return (a,s)
m `tbind` k = S $ \s -> unS m s >>= \ ~(a, s') -> unS (k a) s'
instance (MonadFix m) => MonadFix (StateT s m) where
mfix f = S $ \s -> mfix (runStateT s . f . fst)
instance FMonadT (StateT s) where
tmap' d1 _d2 g f (S m) = S (f . fmapD d1 (\(x,s) -> (g x,s)) . m)
instance MMonadT (StateT s) where
flift t = S (\s -> fmap (\a -> (a,s)) t)
monoidalT (S t) = S (\s -> Comp $ fmap (\(S t',s') -> t' s') (t s))
newtype WriterT w m a = W {unW :: m (a,w) }
writerT :: (Monoid w, Monad m) => m (a,w) -> WriterT w m a
writerT = W
runWriterT :: (Monoid w) => WriterT w m a -> m (a,w)
runWriterT = unW
instance Monoid w => MonadT (WriterT w) where
tbind (W m) f = W (do (a,w) <- m
(a',w') <- unW (f a)
return (a',w `mappend` w'))
lift m = W (liftM (\a -> (a,mempty)) m)
instance Monoid w => FMonadT (WriterT w) where
tmap' d1 _d2 g f = W . f . fmapD d1 (\(x,s) -> (g x,s)) . unW
instance Monoid w => MMonadT (WriterT w) where
flift t = W (fmap (\a -> (a,mempty)) t)
monoidalT (W t) = W $ Comp $ fmap (\(W t',w) ->
fmap (\(a,w') -> (a,w `mappend` w')) t') $ t
newtype ReaderT s m a = R { unR :: s -> m a }
runReaderT :: s -> ReaderT s m a -> m a
runReaderT s m = unR m s
instance MonadT (ReaderT s) where
tbind m k = R (\s -> unR m s >>= \a -> unR (k a) s)
lift m = R (\_ -> m)
readerT :: Monad m => (e -> m a) -> ReaderT e m a
readerT = R
instance FMonadT (ReaderT s) where
tmap' d1 _d2 g f (R m) = R (f . fmapD d1 g . m)
instance MMonadT (ReaderT s) where
flift t = R (\_ -> t)
monoidalT (R t) = R (\s -> Comp $ fmap (($ s) . unR) (t s))
newtype ExcT x m a = X {unX :: m (Either x a)}
excT :: Monad m => m (Either x a) -> ExcT x m a
excT = X
runExcT :: Monad m => ExcT x m a -> m (Either x a)
runExcT = unX
instance (MonadFix m) => MonadFix (ExcT x m) where
mfix f = X $ mfix (unX . f . fromRight)
where fromRight (Right a) = a
fromRight _ = error "ExceptionT: mfix looped."
instance MonadT (ExcT x) where
lift m = X (liftM Right m)
(X m) `tbind` f = X (do a <- m
case a of
Left x -> return (Left x)
Right b -> unX (f b))
instance FMonadT (ExcT x) where
tmap' d1 _d2 g f = X . f . fmapD d1 func . unX where
func (Left x) = Left x
func (Right y) = Right (g y)
newtype ContT r m a = C {unC :: (a -> m r) -> m r}
runContT :: (a -> m r) -> ContT r m a -> m r
runContT = flip unC
contT :: ((a -> m r) -> m r) -> ContT r m a
contT = C
instance MonadT (ContT r) where
lift m = C (m >>=)
m `tbind` k = C $ \c -> unC m (\a -> unC (k a) c)
data LSig f a b = NilT b
| ConsT a (f a)
newtype ListT m a = L {unL :: m (LSig (ListT m) a ())}
runListT :: ListT m a -> m (LSig (ListT m) a ())
runListT = unL
listT :: m (LSig (ListT m) a ()) -> ListT m a
listT = L
emptyL :: Monad m => ListT m a
emptyL = L $ return $ NilT ()
appendL :: Monad m=> ListT m a -> ListT m a -> ListT m a
appendL (L m1) (L m2) = L $ do
l <- m1
case l of
NilT () -> m2
ConsT a l1 -> return (ConsT a (appendL l1 (L m2)))
foldListT :: Monad m => (a -> m b -> m b) -> m b -> ListT m a -> m b
foldListT c n (L m) = do l <- m
case l of
NilT () -> n
ConsT a l1 -> c a (foldListT c n l1)
collectListT :: Monad m => ListT m a -> m [a]
collectListT lt = foldListT (\a m -> m >>= return. (a:)) (return []) lt
instance MonadT ListT where
lift m = L $ liftM (`ConsT` emptyL) m
m `tbind` f = L $ foldListT (\a l -> unL $ f a `appendL` L l)
(return $ NilT ())
m
instance FMonadT ListT where
tmap' d1 d2 g t (L m) = L $ t $ fmapD d1 (\lsig -> case lsig of
NilT () -> NilT ()
ConsT a l -> ConsT (g a) (tmap' d1 d2 g t l)) m
newtype StepT f m x = T {runT :: m (Either x (f (StepT f m x)))}
stepT :: m (Either x (f (StepT f m x))) -> StepT f m x
stepT = T
runStepT :: StepT f m x -> m (Either x (f (StepT f m x)))
runStepT = runT
caseStepT :: (Functor f, Monad m) =>
(a -> StepT f m x) -> (f (StepT f m a) -> StepT f m x)
-> StepT f m a -> StepT f m x
caseStepT v c (T m) = T (m >>= either (runT . v) (runT . c))
unfoldStepT :: (Functor f, Monad m) => (y -> m (Either x (f y))) -> y -> StepT f m x
unfoldStepT k y = T (liftM (fmap (fmap (unfoldStepT k))) (k y))
instance (Functor f) => MonadT (StepT f) where
tbind t f = caseStepT f (T . return . Right . fmap (`tbind` f)) t
lift = T . liftM Left
instance (Functor f) => FMonadT (StepT f) where
tmap' d1 d2 g t (T m) = T (t (fmapD d1 (either (Left . g) (Right . fmap (tmap' d1 d2 g t))) m))