module Data.EitherR (
EitherR(..),
succeed,
throwE,
catchE,
handleE,
fmapL,
flipE,
EitherRT(..),
succeedT,
throwT,
catchT,
handleT,
fmapLT,
flipET,
) where
import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))
import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Monad.IO.Class (MonadIO(liftIO))
import Control.Monad.Trans.Either (EitherT(EitherT, runEitherT), left, right)
import Data.Monoid (Monoid(mempty, mappend))
newtype EitherR r e = EitherR { runEitherR :: Either e r }
instance Functor (EitherR r) where
fmap = liftM
instance Applicative (EitherR r) where
pure = return
(<*>) = ap
instance Monad (EitherR r) where
return e = EitherR (Left e)
EitherR m >>= f = case m of
Left e -> f e
Right r -> EitherR (Right r)
instance (Monoid r) => Alternative (EitherR r) where
empty = EitherR (Right mempty)
e1@(EitherR (Left _)) <|> _ = e1
_ <|> e2@(EitherR (Left _)) = e2
EitherR (Right r1) <|> EitherR (Right r2)
= EitherR (Right (mappend r1 r2))
instance (Monoid r) => MonadPlus (EitherR r) where
mzero = empty
mplus = (<|>)
succeed :: r -> EitherR r e
succeed r = EitherR (return r)
throwE :: e -> Either e r
throwE e = runEitherR (return e)
catchE :: Either a r -> (a -> Either b r) -> Either b r
e `catchE` f = runEitherR $ EitherR e >>= \a -> EitherR (f a)
handleE :: (a -> Either b r) -> Either a r -> Either b r
handleE = flip catchE
fmapL :: (a -> b) -> Either a r -> Either b r
fmapL f = runEitherR . fmap f . EitherR
flipE :: Either a b -> Either b a
flipE e = case e of
Left a -> Right a
Right b -> Left b
newtype EitherRT r m e = EitherRT { runEitherRT :: EitherT e m r }
instance (Monad m) => Functor (EitherRT r m) where
fmap = liftM
instance (Monad m) => Applicative (EitherRT r m) where
pure = return
(<*>) = ap
instance (Monad m) => Monad (EitherRT r m) where
return e = EitherRT (left e)
m >>= f = EitherRT $ EitherT $ do
x <- runEitherT $ runEitherRT m
runEitherT $ runEitherRT $ case x of
Left e -> f e
Right r -> EitherRT (right r)
instance (Monad m, Monoid r) => Alternative (EitherRT r m) where
empty = EitherRT $ EitherT $ return $ Right mempty
e1 <|> e2 = EitherRT $ EitherT $ do
x1 <- runEitherT $ runEitherRT e1
case x1 of
Left l -> return (Left l)
Right r1 -> do
x2 <- runEitherT $ runEitherRT e2
case x2 of
Left l -> return (Left l)
Right r2 -> return (Right (mappend r1 r2))
instance (Monad m, Monoid r) => MonadPlus (EitherRT r m) where
mzero = empty
mplus = (<|>)
instance MonadTrans (EitherRT r) where
lift = EitherRT . EitherT . liftM Left
instance (MonadIO m) => MonadIO (EitherRT r m) where
liftIO = lift . liftIO
succeedT :: (Monad m) => r -> EitherRT r m e
succeedT r = EitherRT (return r)
throwT :: (Monad m) => e -> EitherT e m r
throwT e = runEitherRT (return e)
catchT :: (Monad m) => EitherT a m r -> (a -> EitherT b m r) -> EitherT b m r
e `catchT` f = runEitherRT $ EitherRT e >>= \a -> EitherRT (f a)
handleT :: (Monad m) => (a -> EitherT b m r) -> EitherT a m r -> EitherT b m r
handleT = flip catchT
fmapLT :: (Monad m) => (a -> b) -> EitherT a m r -> EitherT b m r
fmapLT f = runEitherRT . fmap f . EitherRT
flipET :: (Monad m) => EitherT a m b -> EitherT b m a
flipET = EitherT . liftM flipE . runEitherT