module Data.Neither
(
AEither (..)
, aeither
, MEither (..)
, meither
, MEitherT (..)
, mapMEitherT
, throwMEither
, Neither (..)
, mapLeft
, mapRight
, mapEither
, lefts
, rights
, partitionEithers
) where
import Prelude hiding (either, catch)
import qualified Data.Either as E
import Control.Monad
import Control.Arrow ((&&&))
import Data.Monoid
import Control.Applicative
import Control.Failure
import Data.Typeable
import Data.Data
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
class Neither e where
left :: a -> e a b
right :: b -> e a b
either :: (a -> c) -> (b -> c) -> e a b -> c
instance Neither Either where
left = Left
right = Right
either = E.either
instance Neither MEither where
left = MLeft
right = MRight
either = meither
instance Neither AEither where
left = ALeft
right = ARight
either = aeither
mapLeft :: Neither e => (a -> c) -> e a b -> e c b
mapLeft = flip mapEither id
mapRight :: Neither e => (b -> c) -> e a b -> e a c
mapRight = mapEither id
mapEither :: Neither e => (a -> c) -> (b -> d) -> e a b -> e c d
mapEither f g = either (left . f) (right . g)
lefts :: (Neither e, MonadPlus m) => m (e a b) -> m a
lefts = (=<<) $ either return (const mzero)
rights :: (Neither e, MonadPlus m) => m (e a b) -> m b
rights = (=<<) $ either (const mzero) return
partitionEithers :: (Neither e, MonadPlus m) => m (e a b) -> (m a, m b)
partitionEithers = lefts &&& rights
data MEither a b = MLeft a | MRight b
deriving (Typeable, Eq, Data, Ord, Read, Show)
instance Monad (MEither a) where
return = MRight
(MLeft a) >>= _ = MLeft a
(MRight b) >>= f = f b
instance Functor (MEither a) where
fmap = liftM
instance Applicative (MEither a) where
pure = return
(<*>) = ap
instance Failure e (MEither e) where
failure = MLeft
meither :: (a -> c) -> (b -> c) -> MEither a b -> c
meither f _ (MLeft a) = f a
meither _ f (MRight b) = f b
data AEither a b = ALeft a | ARight b
deriving (Typeable, Eq, Data, Ord, Read, Show)
instance Functor (AEither a) where
fmap _ (ALeft a) = ALeft a
fmap f (ARight b) = ARight $ f b
instance Monoid a => Applicative (AEither a) where
pure = ARight
ALeft x <*> ALeft y = ALeft $ x `mappend` y
ALeft x <*> _ = ALeft x
_ <*> ALeft y = ALeft y
ARight x <*> ARight y = ARight $ x y
aeither :: (a -> c) -> (b -> c) -> AEither a b -> c
aeither f _ (ALeft a) = f a
aeither _ f (ARight b) = f b
newtype MEitherT e m a = MEitherT
{ runMEitherT :: m (MEither e a)
}
mapMEitherT :: (m (MEither e a) -> n (MEither e' b))
-> MEitherT e m a
-> MEitherT e' n b
mapMEitherT f m = MEitherT $ f (runMEitherT m)
throwMEither :: Monad m => e -> MEitherT e m a
throwMEither = MEitherT . return . MLeft
instance Functor m => Functor (MEitherT e m) where
fmap f = MEitherT . fmap (fmap f) . runMEitherT
instance (Functor m, Monad m) => Applicative (MEitherT e m) where
pure = return
(<*>) = ap
instance Monad m => Monad (MEitherT e m) where
return = MEitherT . return . return
(MEitherT x) >>= f = MEitherT $
x >>= meither (return . MLeft) (runMEitherT . f)
instance Monad m => Failure e (MEitherT e m) where
failure = MEitherT . return . MLeft
instance MonadTrans (MEitherT e) where
lift = MEitherT . liftM MRight
instance MonadIO m => MonadIO (MEitherT e m) where
liftIO = lift . liftIO