Difference between revisions of "New monads/MaybeT"

From HaskellWiki
Jump to navigation Jump to search
(Add Reader and Writer instances)
(Changed mplus to shortcut as one would expect)
 
(2 intermediate revisions by one other user not shown)
Line 7: Line 7:
   
 
module Control.Monad.Maybe
 
module Control.Monad.Maybe
(MaybeT(runMaybeT),
+
(MaybeT,
  +
runMaybeT,
 
module Control.Monad,
 
module Control.Monad,
 
module Control.Monad.Trans)
 
module Control.Monad.Trans)
Line 15: Line 16:
 
import Control.Monad.Trans
 
import Control.Monad.Trans
 
import Control.Monad.State
 
import Control.Monad.State
  +
import Control.Monad.Reader
  +
import Control.Monad.Writer
   
 
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
 
newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}
Line 28: Line 31:
 
instance Monad m => MonadPlus (MaybeT m) where
 
instance Monad m => MonadPlus (MaybeT m) where
 
mzero = MaybeT $ return Nothing
 
mzero = MaybeT $ return Nothing
mplus x y = MaybeT $ liftM2 mplus (runMaybeT x) (runMaybeT y)
+
mplus x y = MaybeT $ do
  +
mx <- runMaybeT x
  +
case mx of
  +
Nothing -> runMaybeT y
  +
Just _ -> return mx
   
 
-- Provide other MTL instances, for convenience
 
-- Provide other MTL instances, for convenience
Line 37: Line 44:
 
-- (Add other MTL instances, and a MonadFix instance)
 
-- (Add other MTL instances, and a MonadFix instance)
   
instance MonadIO m => MonadIO (maybeT m) where
+
instance MonadIO m => MonadIO (MaybeT m) where
 
liftIO = lift . liftIO
 
liftIO = lift . liftIO
   

Latest revision as of 02:24, 18 March 2008

The Maybe monad deserves a transformer, just like the other classic monads.

The code

{-# OPTIONS_GHC -fglasgow-exts  -fallow-undecidable-instances #-}

module Control.Monad.Maybe
  (MaybeT,
   runMaybeT,
   module Control.Monad,
   module Control.Monad.Trans)
where

import Control.Monad
import Control.Monad.Trans
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Writer

newtype MaybeT m a = MaybeT {runMaybeT :: m (Maybe a)}

instance Functor m => Functor (MaybeT m) where
  fmap f x = MaybeT $ fmap (fmap f) $ runMaybeT x

instance Monad m => Monad (MaybeT m) where
  return = MaybeT . return . Just
  x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)
  fail _ = MaybeT $ return Nothing

instance Monad m => MonadPlus (MaybeT m) where
  mzero = MaybeT $ return Nothing
  mplus x y = MaybeT $ do
    mx <- runMaybeT x
    case mx of
      Nothing -> runMaybeT y
      Just _  -> return mx

-- Provide other MTL instances, for convenience

instance MonadTrans MaybeT where
  lift = MaybeT . liftM Just

-- (Add other MTL instances, and a MonadFix instance)

instance MonadIO m => MonadIO (MaybeT m) where
  liftIO = lift . liftIO

instance MonadState s m => MonadState s (MaybeT m) where
  get = lift get
  put = lift . put

instance MonadReader r m => MonadReader r (MaybeT m) where
  ask = lift ask
  local f = MaybeT . local f . runMaybeT

instance (Monoid w, MonadWriter w m) => MonadWriter w (MaybeT m) where
  tell = lift . tell
  listen m = MaybeT (do (mv,w) <- listen (runMaybeT m)
                        case mv of
                          Nothing -> return Nothing
                          Just v -> return (Just (v,w)))
  pass m = MaybeT (do mvf <- runMaybeT m
                      case mvf of
                        Nothing -> return Nothing
                        Just (v,f) -> pass (return (Just v,f)))