{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, Safe #-}
module Data.Chatty.Fail where
import Control.Applicative
import Control.Monad
import Control.Monad.Identity
import Control.Monad.Error.Class
import Control.Monad.Trans.Class
newtype FailT e m a = Fail { FailT e m a -> m (Either e a)
runFailT :: m (Either e a) }
type Fail e = FailT e Identity
instance Monad m => Functor (FailT e m) where
fmap :: (a -> b) -> FailT e m a -> FailT e m b
fmap a -> b
f FailT e m a
a = m (Either e b) -> FailT e m b
forall e (m :: * -> *) a. m (Either e a) -> FailT e m a
Fail (m (Either e b) -> FailT e m b) -> m (Either e b) -> FailT e m b
forall a b. (a -> b) -> a -> b
$ do
Either e a
v <- FailT e m a -> m (Either e a)
forall e (m :: * -> *) a. FailT e m a -> m (Either e a)
runFailT FailT e m a
a
case Either e a
v of
Left e
e -> Either e b -> m (Either e b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either e b -> m (Either e b)) -> Either e b -> m (Either e b)
forall a b. (a -> b) -> a -> b
$ e -> Either e b
forall a b. a -> Either a b
Left e
e
Right a
x -> Either e b -> m (Either e b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either e b -> m (Either e b)) -> Either e b -> m (Either e b)
forall a b. (a -> b) -> a -> b
$ b -> Either e b
forall a b. b -> Either a b
Right (a -> b
f a
x)
instance Monad m => Applicative (FailT e m) where
pure :: a -> FailT e m a
pure = a -> FailT e m a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: FailT e m (a -> b) -> FailT e m a -> FailT e m b
(<*>) = FailT e m (a -> b) -> FailT e m a -> FailT e m b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad m => Monad (FailT e m) where
return :: a -> FailT e m a
return a
a = m (Either e a) -> FailT e m a
forall e (m :: * -> *) a. m (Either e a) -> FailT e m a
Fail (m (Either e a) -> FailT e m a) -> m (Either e a) -> FailT e m a
forall a b. (a -> b) -> a -> b
$ Either e a -> m (Either e a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either e a -> m (Either e a)) -> Either e a -> m (Either e a)
forall a b. (a -> b) -> a -> b
$ a -> Either e a
forall a b. b -> Either a b
Right a
a
FailT e m a
m >>= :: FailT e m a -> (a -> FailT e m b) -> FailT e m b
>>= a -> FailT e m b
f = m (Either e b) -> FailT e m b
forall e (m :: * -> *) a. m (Either e a) -> FailT e m a
Fail (m (Either e b) -> FailT e m b) -> m (Either e b) -> FailT e m b
forall a b. (a -> b) -> a -> b
$ do
Either e a
v <- FailT e m a -> m (Either e a)
forall e (m :: * -> *) a. FailT e m a -> m (Either e a)
runFailT FailT e m a
m
case Either e a
v of
Left e
e -> Either e b -> m (Either e b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either e b -> m (Either e b)) -> Either e b -> m (Either e b)
forall a b. (a -> b) -> a -> b
$ e -> Either e b
forall a b. a -> Either a b
Left e
e
Right a
x -> FailT e m b -> m (Either e b)
forall e (m :: * -> *) a. FailT e m a -> m (Either e a)
runFailT (FailT e m b -> m (Either e b)) -> FailT e m b -> m (Either e b)
forall a b. (a -> b) -> a -> b
$ a -> FailT e m b
f a
x
instance MonadTrans (FailT e) where
lift :: m a -> FailT e m a
lift m a
m = m (Either e a) -> FailT e m a
forall e (m :: * -> *) a. m (Either e a) -> FailT e m a
Fail (m (Either e a) -> FailT e m a) -> m (Either e a) -> FailT e m a
forall a b. (a -> b) -> a -> b
$ do
a
a <- m a
m
Either e a -> m (Either e a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either e a -> m (Either e a)) -> Either e a -> m (Either e a)
forall a b. (a -> b) -> a -> b
$ a -> Either e a
forall a b. b -> Either a b
Right a
a
instance Monad m => MonadError e (FailT e m) where
throwError :: e -> FailT e m a
throwError e
e = m (Either e a) -> FailT e m a
forall e (m :: * -> *) a. m (Either e a) -> FailT e m a
Fail (m (Either e a) -> FailT e m a) -> m (Either e a) -> FailT e m a
forall a b. (a -> b) -> a -> b
$ Either e a -> m (Either e a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either e a -> m (Either e a)) -> Either e a -> m (Either e a)
forall a b. (a -> b) -> a -> b
$ e -> Either e a
forall a b. a -> Either a b
Left e
e
catchError :: FailT e m a -> (e -> FailT e m a) -> FailT e m a
catchError FailT e m a
m e -> FailT e m a
h = m (Either e a) -> FailT e m a
forall e (m :: * -> *) a. m (Either e a) -> FailT e m a
Fail (m (Either e a) -> FailT e m a) -> m (Either e a) -> FailT e m a
forall a b. (a -> b) -> a -> b
$ do
Either e a
v <- FailT e m a -> m (Either e a)
forall e (m :: * -> *) a. FailT e m a -> m (Either e a)
runFailT FailT e m a
m
case Either e a
v of
Left e
e -> FailT e m a -> m (Either e a)
forall e (m :: * -> *) a. FailT e m a -> m (Either e a)
runFailT (FailT e m a -> m (Either e a)) -> FailT e m a -> m (Either e a)
forall a b. (a -> b) -> a -> b
$ e -> FailT e m a
h e
e
Right a
x -> Either e a -> m (Either e a)
forall (m :: * -> *) a. Monad m => a -> m a
return Either e a
v