module Algebra.Monad.Error (
MonadError(..),try,(!+),optional,throwIO,
EitherT,
eitherT
) where
import Algebra.Monad.Base
import qualified Control.Exception as Ex
try :: MonadError e m => m a -> m a -> m a
try = catch . const
optional :: MonadError e m => m a -> m (Maybe a)
optional m = catch (\_ -> return Nothing) (Just<$>m)
(!+) :: MonadError Void m => m a -> m a -> m a
(!+) = flip try
infixr 0 !+
instance MonadError e (Either e) where
throw = Left
catch f = f<|>Right
instance MonadError Void [] where
throw = const zero
catch f [] = f zero
catch _ l = l
newtype EitherT e m a = EitherT (Compose' (Either e) m a)
deriving (Unit,Functor,SemiApplicative,Applicative,MonadFix,Foldable,MonadTrans)
instance Monad m => Monad (EitherT e m) where join = coerceJoin EitherT
instance Traversable m => Traversable (EitherT e m) where sequence = coerceSequence EitherT
eitherT :: Iso (EitherT e m a) (EitherT f m b) (m (e:+:a)) (m (f:+:b))
eitherT = i'Compose'.iso EitherT (\(EitherT e) -> e)
instance MonadError Void Maybe where
throw = const Nothing
catch f Nothing = f zero
catch _ a = a
instance MonadError Ex.SomeException IO where
throw = Ex.throw
catch = flip Ex.catch
throwIO :: (MonadError Ex.SomeException m,Ex.Exception e) => e -> m ()
throwIO = throw . Ex.toException