packages feed

FailureT-15778.1: Control/Monad/Failure.hs

module Control.Monad.Failure (module Control.Monad.Failure.Class, FailureT (..)) where

import Prelude hiding (fail);

import Control.Applicative;
import Control.Category.Unicode;
import Control.Monad hiding (fail);
import Control.Monad.Fix;
import Control.Monad.Trans;
import Control.Monad.Failure.Class;
import Data.Traversable;

newtype FailureT f m a = FailureT { runFailureT :: m (Either f a) };

mapFailureT :: (m (Either f a) -> n (Either f b)) -> FailureT f m a -> FailureT f n b;
mapFailureT f = FailureT ∘ f ∘ runFailureT;

instance MonadTrans (FailureT f) where {
  lift = FailureT ∘ liftM Right;
  tmap f _ = mapFailureT f;
};

instance Functor m => Functor (FailureT f m) where {
  fmap = mapFailureT ∘ fmap ∘ fmap;
};

instance Applicative m => Applicative (FailureT f m) where {
  pure = FailureT ∘ pure ∘ Right;
  FailureT f <*> FailureT x = let {
    go (Right φ) (Right χ) = Right (φ χ);
    go (Right _) (Left  e) = Left e;
    go (Left  e)  _        = Left e;
  } in FailureT (liftA2 go f x);
};

instance Monad m => Monad (FailureT f m) where {
  return = lift ∘ return;
  FailureT x >>= f = FailureT $ x >>= liftM join ∘ either (liftM Left ∘ return) (liftM Right ∘ runFailureT ∘ f);
};

instance MonadFix m => MonadFix (FailureT f m) where {
  mfix f = FailureT $ mfix (either (return ∘ Left) (runFailureT ∘ f));
};

instance (Monad m, MonadTrans xT, Monad (xT (FailureT f m))) => MonadFailure f (xT (FailureT f m)) where {
  fail = lift ∘ fail;
};

instance Monad m => MonadFailure f (FailureT f m) where {
  fail = FailureT ∘ return ∘ Left;
};

instance Monad m => MonadSalvage f (FailureT f m) where {
  save f = mapFailureT (>>= runFailureT ∘ either f return);
};