Bheklilr's answer gave me an idea of ββan example in which a monad transformer creates something that is not a monad. A well-known example of something that is not a monad is a ZipList . And we can make a variant that performs a monadic action at each level:
import Control.Applicative import Control.Arrow ((***)) import Control.Monad import Control.Monad.Trans -- | A list where each step is produced by a monadic action. data ListT ma = Nil | Cons (m (a, ListT ma))
This is actually a monad stream. And it can be easily turned into Functor and Applicative
instance Monad m => Functor (ListT m) where fmap f Nil = Nil fmap f (Cons k) = Cons $ (f *** fmap f) `liftM` k instance Monad m => Applicative (ListT m) where pure x = Cons $ return (x, pure x) Cons mf <*> Cons mx = Cons $ do (f, fs) <- mf (x, xs) <- mx return (fx, fs <*> xs) _ <*> _ = Nil
but obviously not a monad. So, we have a MonadTrans instance that converts the monad into something that is only Applicative .
instance MonadTrans ListT where lift mx = Cons $ (\x -> (x, lift mx)) `liftM` mx
(All this made me realize that the experimental ZipSink in the optional cable is also a good example.)
However, this raises another question: if we want such transformers, what laws should they adhere to? Laws for MonadTrans defined as
lift . return = return lift (m >>= f) = lift m >>= (lift . f)
So, in our case, we might wish for something like
lift (f `liftM` x) = fmap f (lift x) lift . return = pure lift (m `ap` f) = lift m <*> lift f
source share