{-# LANGUAGE InstanceSigs #-} module MaybeT where import Control.Monad 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 . Just (<*>) :: MaybeT m (a -> b) -> MaybeT m a -> MaybeT m b f <*> x = MaybeT $ fmap (<*>) (runMaybeT f) <*> runMaybeT x -- 2nd (outer) <*> in Applicative m: -- (<*>) :: m (Maybe a -> Maybe b) -- -> m (Maybe a) -> m (Maybe b) -- fmap (<*>) :: m (Maybe (a -> b)) -- -> m (Maybe a -> Maybe b) 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)