{-# LANGUAGE InstanceSigs #-} module MaybeT where import Control.Applicative newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } instance (Functor m) => Functor (MaybeT m) where fmap :: (a -> b) -> MaybeT m a -> MaybeT m b fmap f = MaybeT . fmap (fmap f) . runMaybeT -- 1st fmap from Functor m -- 2nd fmap from Functor Maybe instance Applicative m => Applicative (MaybeT m) where pure :: a -> MaybeT m a pure = MaybeT . pure . pure (<*>) :: MaybeT m (a -> b) -> MaybeT m a -> MaybeT m b f <*> x = MaybeT $ liftA2 (<*>) (runMaybeT f) (runMaybeT x) instance Monad m => Monad (MaybeT m) where (>>=) :: MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b x >>= f = MaybeT $ do -- do in Monad m mx <- runMaybeT x -- mx :: Maybe a case mx of Nothing -> return Nothing Just px -> runMaybeT (f px) -- px :: a return = pure fail _ = MaybeT (return Nothing) liftMaybeT :: Monad m => m a -> MaybeT m a liftMaybeT x = MaybeT (Just <$> x)