Difference between revisions of "New monads/MaybeT"

From HaskellWiki
Jump to navigation Jump to search
(Added Category:Code)
(Changed mplus to shortcut as one would expect)
 
(7 intermediate revisions by 3 users not shown)
Line 3: Line 3:
 
== The code ==
 
== The code ==
   
  +
<haskell>
{-# OPTIONS_GHC -fglasgow-exts #-}
+
{-# OPTIONS_GHC -fglasgow-exts -fallow-undecidable-instances #-}
   
 
module Control.Monad.Maybe
 
module Control.Monad.Maybe
(MaybeT(runMaybeT),
+
(MaybeT,
  +
runMaybeT,
 
module Control.Monad,
 
module Control.Monad,
module Control.Monad.Fix,
 
 
module Control.Monad.Trans)
 
module Control.Monad.Trans)
 
where
 
where
   
 
import Control.Monad
 
import Control.Monad
import Control.Monad.Fix
 
 
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 23: Line 25:
   
 
instance Monad m => Monad (MaybeT m) where
 
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . return
+
return = MaybeT . return . Just
 
x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)
 
x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f)
 
fail _ = MaybeT $ return Nothing
 
fail _ = MaybeT $ return Nothing
   
 
instance Monad m => MonadPlus (MaybeT m) where
 
instance Monad m => MonadPlus (MaybeT m) where
mzero = MaybeT $ return mzero
+
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
   
 
instance MonadTrans MaybeT where
 
instance MonadTrans MaybeT where
lift = MaybeT . liftM return
+
lift = MaybeT . liftM Just
   
 
-- (Add other MTL instances, and a MonadFix instance)
 
-- (Add other MTL instances, and a MonadFix instance)
   
  +
instance MonadIO m => MonadIO (MaybeT m) where
[Category:Code]]
 
  +
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)))
  +
  +
  +
</haskell>
  +
 
[[Category:Code]]

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)))