{-# LANGUAGE GADTs #-} module MaybeT.Shallow where import qualified Control.Monad.Trans as CMT import qualified Control.Monad as CM -- Monad Transformers -- Shallow embedding (nicer) {- A general pattern for defining a monad transformer is newtype SomeT pars m a = SomeT { runSomeT :: args -> m (something wrapping a) } That is, a computation in the transformed monad is a computation in the underlying monad with a more interesting result type, possibly with some additional arguments. From the libraries: -- args "something wrapping a" StateT: s -> m (a, s) ReaderT: e -> m a WriterT: m (a, w) ErrorT: m (Either e a) -- Reader, Writer and State all at once: RWST: e -> s -> m (a, s, w) -} -- For our case: no args and "Maybe" wrapping a newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } instance Monad m => Monad (MaybeT m) where return = returnMT (>>=) = bindMT fail = failMT returnMT :: Monad m => a -> MaybeT m a returnMT x = MaybeT $ return (Just x) bindMT :: Monad m => MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b bindMT m f = MaybeT $ do -- in the Monad m r <- runMaybeT m case r of Nothing -> return Nothing Just x -> runMaybeT (f x) failMT :: Monad m => t -> MaybeT m a failMT _ = MaybeT (return Nothing) instance CMT.MonadTrans MaybeT where lift = liftMT liftMT :: Monad m => m a -> MaybeT m a liftMT m = MaybeT (CM.liftM Just m)