EitherT-0.2.0: src/Control/Monad/Trans/Either.hs
{-# OPTIONS -Wall -O2 -fno-warn-orphans #-}
{-# LANGUAGE CPP, FlexibleInstances, MultiParamTypeClasses,
UndecidableInstances, TypeFamilies #-}
module Control.Monad.Trans.Either(EitherT(..), left) where
import Data.Monoid(Monoid(..))
import Control.Monad(liftM)
import Control.Monad.Trans.Class(MonadTrans(..))
import Control.Monad.Instances()
import Control.Monad.IO.Class(MonadIO(..))
import Control.Applicative(Applicative(..), liftA2)
import Control.Monad.Base
import Control.Monad.Trans.Control
newtype EitherT l m a = EitherT { runEitherT :: m (Either l a) }
inEitherT0 :: m (Either l a) -> EitherT l m a
inEitherT0 = EitherT
inEitherT1 :: (m (Either l a) -> m (Either l b)) ->
EitherT l m a -> EitherT l m b
inEitherT1 f = inEitherT0 . f . runEitherT
inEitherT2 :: (m (Either l a) -> m (Either l b) -> m (Either l c)) ->
EitherT l m a -> EitherT l m b -> EitherT l m c
inEitherT2 f = inEitherT1 . f . runEitherT
left :: Monad m => l -> EitherT l m a
left = EitherT . return . Left
instance Monad m => Monad (EitherT l m) where
-- We can't support "fail" because we don't have a
-- (String -> l). But we can at least make it a Left, with the error inside
-- it as a pure exception.
fail = EitherT . return . Left . error
return = EitherT . return . Right
EitherT x >>= f = EitherT $ do
res <- x
case res of
Right r -> runEitherT . f $ r
Left l -> return (Left l)
instance MonadTrans (EitherT l) where
lift = EitherT . liftM Right
instance Functor f => Functor (EitherT l f) where
fmap = inEitherT1 . fmap . fmap
instance Applicative f => Applicative (EitherT l f) where
pure = inEitherT0 . pure . pure
(<*>) = inEitherT2 . liftA2 . liftA2 $ id
instance (MonadIO m) => MonadIO (EitherT l m) where
liftIO = lift . liftIO
instance (Applicative m, Monoid a) => Monoid (EitherT l m a) where
mempty = pure mempty
mappend = liftA2 mappend
instance MonadBase b m => MonadBase b (EitherT l m) where
liftBase = liftBaseDefault
instance MonadTransControl (EitherT l) where
newtype StT (EitherT l) r = StEither {unStEither :: Either l r}
liftWith f = EitherT $ liftM return $ f $ liftM StEither . runEitherT
restoreT = EitherT . liftM unStEither
{-# INLINE liftWith #-}
{-# INLINE restoreT #-}
{-
instance (MonadBaseControl b m) => MonadBaseControl b (Either l m) where
newType StM (EitherT l m) a = StMEither { unStMEither :: ComposeSt (EitherT l) m a }
liftBaseWith = defaultLiftBaseWith StMEither
restoreM = defaultRestoreM unSTMEither
{-# INLINE liftBaseWith #-}
{-# INLINE restoreM #-}
-}
--Copied from monad-control-0.3.1.1.
#define BODY(T, ST, unST) { \
newtype StM (T m) a = ST {unST :: ComposeSt (T) m a}; \
liftBaseWith = defaultLiftBaseWith ST; \
restoreM = defaultRestoreM unST; \
{-# INLINE liftBaseWith #-}; \
{-# INLINE restoreM #-}}
--Copied from monad-control-0.3.1.1.
#define TRANS( T, ST, unST) \
instance ( MonadBaseControl b m) => MonadBaseControl b (T m) where BODY(T, ST, unST)
TRANS(EitherT l, StMEither, unStMEither)