Hawk-0.0.2: src/Control/Monad/Either.hs
-- --------------------------------------------------------------------------
{- |
Module : Control.Monad.Either
Copyright : Copyright (C) 2009 Björn Peemöller, Stefan Roggensack
License : NONE
Maintainer : {inf6254, inf6509}fh-wedel.de
Stability : experimental
Portability : portable
Version : $Id: Main.hs 57 2009-05-29 11:33:59Z inf6254 $
Monad transformer for Either, inspired by Control.Monad.ErrorT but without
the Error restriction of the Left value.
-}
-- --------------------------------------------------------------------------
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}
module Control.Monad.Either
( EitherT (..)
, returnLeft
, mapEitherT
, module Control.Monad
, module Control.Monad.Fix
, module Control.Monad.Trans
) where
import Control.Monad
import Control.Monad.CatchIO
import Control.Monad.Fix
import Control.Monad.RWS.Class
import Control.Monad.Trans
import Prelude hiding (catch)
-- --------------------------------------------------------------------------
-- instances for Either
-- --------------------------------------------------------------------------
{-
instance Monad (Either e) where
return = Right
Right m >>= k = k m
Left e >>= _ = Left e
instance Applicative (Either e) where
pure = Right
a <*> b = do x <- a; y <- b; return (x y)
instance MonadFix (Either e) where
mfix f = let
a = f $ case a of
Right r -> r
_ -> error "empty mfix argument"
in a
-}
-- --------------------------------------------------------------------------
-- Definitions for EitherT
-- --------------------------------------------------------------------------
newtype EitherT a m b = EitherT { runEitherT :: m (Either a b) }
returnLeft :: Monad m => a -> EitherT a m b
returnLeft = EitherT . return . Left
mapEitherT :: (m (Either a b) -> n (Either a' b'))
-> EitherT a m b
-> EitherT a' n b'
mapEitherT f = EitherT . f . runEitherT
-- --------------------------------------------------------------------------
-- instances for EitherT
-- --------------------------------------------------------------------------
instance Functor f => Functor (EitherT a f) where
fmap f = EitherT . fmap (fmap f) . runEitherT
instance Monad m => Monad (EitherT a m) where
return = EitherT . return . Right
m >>= k = EitherT $ do
a <- runEitherT m
case a of
Left l -> return (Left l)
Right r -> runEitherT (k r)
instance MonadFix m => MonadFix (EitherT a m) where
mfix f = EitherT $ mfix $ \a -> runEitherT $ f $ case a of
Right r -> r
_ -> error "empty mfix argument"
-- --------------------------------------------------------------------------
-- instances for mtl transformers
-- --------------------------------------------------------------------------
instance MonadTrans (EitherT e) where
lift = EitherT . liftM Right
instance MonadIO m => MonadIO (EitherT e m) where
liftIO = lift . liftIO
instance MonadRWS r w s m => MonadRWS r w s (EitherT e m)
instance MonadReader r m => MonadReader r (EitherT e m) where
ask = lift ask
local f = EitherT . local f . runEitherT
instance MonadState s m => MonadState s (EitherT e m) where
get = lift get
put = lift . put
instance MonadWriter w m => MonadWriter w (EitherT e m) where
tell = lift . tell
listen m = EitherT $ do
(a, w) <- listen $ runEitherT m
case a of
Left l -> return $ Left l
Right r -> return $ Right (r, w)
pass m = EitherT $ pass $ do
a <- runEitherT m
case a of
Left l -> return (Left l, id)
Right (r, f) -> return (Right r, f)
-- --------------------------------------------------------------------------
-- instance for MonadCatchIO
-- --------------------------------------------------------------------------
instance MonadCatchIO m => MonadCatchIO (EitherT e m) where
m `catch` f = mapEitherT (`catch` (runEitherT . f)) m
block = mapEitherT block
unblock = mapEitherT unblock