FailT-0.1.0.0: A 'FailT' monad transformer that plays well with 'MonadFail'
Copyright(c) Alexey Kuleshevich 2022-2023
LicenseBSD3
MaintainerAlexey Kuleshevich <alexey@kuleshevi.ch>
Stabilityexperimental
Portabilitynon-portable
Safe HaskellSafe-Inferred
LanguageHaskell2010

Control.Monad.Trans.Fail

Description

 
Synopsis

Fail

type Fail e = FailT e Identity Source #

FailT transformer with Identity as the base monad.

runFail :: (IsString e, Semigroup e) => Fail e a -> Either e a Source #

Unwrap the pure Fail monad and reveal the underlying result of monadic computation.

>>> runFail (fail "Something went wrong") :: Either String ()
Left "Something went wrong"
>>> runFail (failT "Something went wrong" >> pure ())
Left "Something went wrong"
>>> import Control.Applicative
>>> runFail (failT "Something could have gone wrong" <|> pure ())
Right ()

All errors accrued during the monadic computation will be combined using the Semigroup instance and delimited by a comma:

>>> runFail (fail "One thing went wrong" <|> fail "Another thing went wrong") :: Either String ()
Left "One thing went wrong, Another thing went wrong"

Failing with one of instances functions mempty or empty will yield a no-reason error report:

>>> runFail mempty :: Either String ()
Left "No failure reason given"

runFailLast :: IsString e => Fail e a -> Either e a Source #

This is a variant of runFailAgg where only the error reported for the very last failed computation will be produced and others discarded. This is useful when it is not relevant to retain information about all the attempts and only the last one matters, eg. parsing with backtracking.

runFailAgg :: Fail e a -> Either [e] a Source #

Convert a Fail monad computation in an Either, where the Left will contain all failures in the same order they where received, or Right upon a successful computation.

>>> runFailAgg (fail "One bad thing" <|> fail "Another bad thing") :: Either [String] ()
Left ["One bad thing","Another bad thing"]
>>> runFailAgg (fail "A bad thing" <|> pure "A good thing") :: Either [String] String
Right "A good thing"

errorFail :: (Show e, HasCallStack) => Fail e a -> a Source #

Throw an error if there was a failure, otherwise return the result of computation. Use throwFailT in case you'd like to handle an actual exception in some other underlying monad.

>>> errorFail (fail "This didn't work" :: Fail String ())
*** Exception: "This didn't work"
CallStack (from HasCallStack):
...
>>> errorFail (fail "This didn't work" <|> pure "That Worked" :: Fail String String)
"That Worked"

errorFailWithoutStackTrace :: Show e => Fail e a -> a Source #

Same as errorFail, but without the stack trace:

>>> errorFailWithoutStackTrace (fail "This didn't work" :: Fail String ())
*** Exception: "This didn't work"
>>> errorFailWithoutStackTrace (fail "This didn't work" <|> pure "That Worked" :: Fail String String)
"That Worked"

FailT

newtype FailT e m a Source #

Fail monad transformer that plays well with MonadFail type class.

Constructors

FailT (m (Either [e] a)) 

Instances

Instances details
(IsString e, MonadError e m) => MonadError e (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

throwError :: e -> FailT e m a #

catchError :: FailT e m a -> (e -> FailT e m a) -> FailT e m a #

(IsString e, MonadReader r m) => MonadReader r (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

ask :: FailT e m r #

local :: (r -> r) -> FailT e m a -> FailT e m a #

reader :: (r -> a) -> FailT e m a #

(IsString e, MonadState s m) => MonadState s (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

get :: FailT e m s #

put :: s -> FailT e m () #

state :: (s -> (a, s)) -> FailT e m a #

(IsString e, MonadWriter w m) => MonadWriter w (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

writer :: (a, w) -> FailT e m a #

tell :: w -> FailT e m () #

listen :: FailT e m a -> FailT e m (a, w) #

pass :: FailT e m (a, w -> w) -> FailT e m a #

MonadTrans (FailT e) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

lift :: Monad m => m a -> FailT e m a #

(IsString e, Monad m) => MonadFail (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

fail :: String -> FailT e m a #

(IsString e, MonadIO m) => MonadIO (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

liftIO :: IO a -> FailT e m a #

(IsString e, MonadZip m) => MonadZip (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

mzip :: FailT e m a -> FailT e m b -> FailT e m (a, b) #

mzipWith :: (a -> b -> c) -> FailT e m a -> FailT e m b -> FailT e m c #

munzip :: FailT e m (a, b) -> (FailT e m a, FailT e m b) #

Foldable f => Foldable (FailT e f) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

fold :: Monoid m => FailT e f m -> m #

foldMap :: Monoid m => (a -> m) -> FailT e f a -> m #

foldMap' :: Monoid m => (a -> m) -> FailT e f a -> m #

foldr :: (a -> b -> b) -> b -> FailT e f a -> b #

foldr' :: (a -> b -> b) -> b -> FailT e f a -> b #

foldl :: (b -> a -> b) -> b -> FailT e f a -> b #

foldl' :: (b -> a -> b) -> b -> FailT e f a -> b #

foldr1 :: (a -> a -> a) -> FailT e f a -> a #

foldl1 :: (a -> a -> a) -> FailT e f a -> a #

toList :: FailT e f a -> [a] #

null :: FailT e f a -> Bool #

length :: FailT e f a -> Int #

elem :: Eq a => a -> FailT e f a -> Bool #

maximum :: Ord a => FailT e f a -> a #

minimum :: Ord a => FailT e f a -> a #

sum :: Num a => FailT e f a -> a #

product :: Num a => FailT e f a -> a #

(Eq e, Eq1 m) => Eq1 (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

liftEq :: (a -> b -> Bool) -> FailT e m a -> FailT e m b -> Bool #

(Ord e, Ord1 m) => Ord1 (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

liftCompare :: (a -> b -> Ordering) -> FailT e m a -> FailT e m b -> Ordering #

(Read e, Read1 m) => Read1 (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (FailT e m a) #

liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [FailT e m a] #

liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (FailT e m a) #

liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [FailT e m a] #

(Show e, Show1 m) => Show1 (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> FailT e m a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [FailT e m a] -> ShowS #

Contravariant f => Contravariant (FailT e f) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

contramap :: (a' -> a) -> FailT e f a -> FailT e f a' #

(>$) :: b -> FailT e f b -> FailT e f a #

Traversable f => Traversable (FailT e f) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

traverse :: Applicative f0 => (a -> f0 b) -> FailT e f a -> f0 (FailT e f b) #

sequenceA :: Applicative f0 => FailT e f (f0 a) -> f0 (FailT e f a) #

mapM :: Monad m => (a -> m b) -> FailT e f a -> m (FailT e f b) #

sequence :: Monad m => FailT e f (m a) -> m (FailT e f a) #

Monad m => Alternative (FailT e m) Source #

Short-circuits on the first successful operation, combines failures otherwise.

Instance details

Defined in Control.Monad.Trans.Fail

Methods

empty :: FailT e m a #

(<|>) :: FailT e m a -> FailT e m a -> FailT e m a #

some :: FailT e m a -> FailT e m [a] #

many :: FailT e m a -> FailT e m [a] #

Monad m => Applicative (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

pure :: a -> FailT e m a #

(<*>) :: FailT e m (a -> b) -> FailT e m a -> FailT e m b #

liftA2 :: (a -> b -> c) -> FailT e m a -> FailT e m b -> FailT e m c #

(*>) :: FailT e m a -> FailT e m b -> FailT e m b #

(<*) :: FailT e m a -> FailT e m b -> FailT e m a #

Functor m => Functor (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

fmap :: (a -> b) -> FailT e m a -> FailT e m b #

(<$) :: a -> FailT e m b -> FailT e m a #

(IsString e, Monad m) => Monad (FailT e m) Source #

Short-circuites on the first failing operation.

Instance details

Defined in Control.Monad.Trans.Fail

Methods

(>>=) :: FailT e m a -> (a -> FailT e m b) -> FailT e m b #

(>>) :: FailT e m a -> FailT e m b -> FailT e m b #

return :: a -> FailT e m a #

(IsString e, MonadCont m) => MonadCont (FailT e m) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

callCC :: ((a -> FailT e m b) -> FailT e m a) -> FailT e m a #

(Monad m, Semigroup a) => Monoid (FailT e m a) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

mempty :: FailT e m a #

mappend :: FailT e m a -> FailT e m a -> FailT e m a #

mconcat :: [FailT e m a] -> FailT e m a #

(Monad m, Semigroup a) => Semigroup (FailT e m a) Source #

Executes all monadic actions and combines all successful results using a Semigroup instance. Combines together all failures as well, until a successful operation.

Instance details

Defined in Control.Monad.Trans.Fail

Methods

(<>) :: FailT e m a -> FailT e m a -> FailT e m a #

sconcat :: NonEmpty (FailT e m a) -> FailT e m a #

stimes :: Integral b => b -> FailT e m a -> FailT e m a #

(Read e, Read1 m, Read a) => Read (FailT e m a) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

readsPrec :: Int -> ReadS (FailT e m a) #

readList :: ReadS [FailT e m a] #

readPrec :: ReadPrec (FailT e m a) #

readListPrec :: ReadPrec [FailT e m a] #

(Show e, Show1 m, Show a) => Show (FailT e m a) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

showsPrec :: Int -> FailT e m a -> ShowS #

show :: FailT e m a -> String #

showList :: [FailT e m a] -> ShowS #

(Eq e, Eq1 m, Eq a) => Eq (FailT e m a) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

(==) :: FailT e m a -> FailT e m a -> Bool #

(/=) :: FailT e m a -> FailT e m a -> Bool #

(Ord e, Ord1 m, Ord a) => Ord (FailT e m a) Source # 
Instance details

Defined in Control.Monad.Trans.Fail

Methods

compare :: FailT e m a -> FailT e m a -> Ordering #

(<) :: FailT e m a -> FailT e m a -> Bool #

(<=) :: FailT e m a -> FailT e m a -> Bool #

(>) :: FailT e m a -> FailT e m a -> Bool #

(>=) :: FailT e m a -> FailT e m a -> Bool #

max :: FailT e m a -> FailT e m a -> FailT e m a #

min :: FailT e m a -> FailT e m a -> FailT e m a #

data FailException where Source #

An exception that is produced by the FailT monad transformer.

Constructors

FailException 

Fields

failT :: Applicative m => e -> FailT e m a Source #

Similar to fail, but it is not restricted to String.

runFailT :: (IsString e, Semigroup e, Functor m) => FailT e m a -> m (Either e a) Source #

Similar to runFail, except underlying monad is not restricted to Identity.

Unwrap the FailT monad transformer and produce an action that can be executed in the underlying monad and, which will produce either a comma delimited error message upon a failure or the result otherwise.

>>> runFailT (failT "Could have failed" <|> liftIO (putStrLn "Nothing went wrong"))
Nothing went wrong
Right ()

runFailLastT :: (IsString e, Functor m) => FailT e m a -> m (Either e a) Source #

Similar to runFailLast, except underlying monad is not restricted to Identity.

runFailAggT :: FailT e m a -> m (Either [e] a) Source #

Similar to runFailAgg, except underlying monad is not restricted to Identity.

hoistFailT :: (forall a. m a -> n a) -> FailT e m b -> FailT e n b Source #

Change the underlying monad with the hoisting function.

mapFailT :: (m (Either [e] a) -> n (Either [e] b)) -> FailT e m a -> FailT e n b Source #

Map a function over the underlying representation of the FailT monad.

mapErrorFailT :: Functor m => (e -> e') -> FailT e m a -> FailT e' m a Source #

Map a function over the error type in the FailT monad.

mapErrorsFailT :: Functor m => ([e] -> [e']) -> FailT e m a -> FailT e' m a Source #

Map a function over the aggregation of errors in the FailT monad. Could be used for example for clearing our all of the aggregated error messages:

>>> runFail (mapErrorsFailT (const []) $ failT "Something went wrong") :: Either String ()
Left "No failure reason given"

exceptFailT :: (HasCallStack, Typeable e, Show e, Monad m) => FailT e m a -> ExceptT FailException m a Source #

Convert a FailT computation into an ExceptT.

>>> exceptFailT (fail "A bad thing" >> pure () :: Fail String ())
ExceptT (Identity (Left FailException
"A bad thing"
CallStack (from HasCallStack):
...

throwFailT :: (HasCallStack, Typeable e, Show e, MonadThrow m) => FailT e m a -> m a Source #

Use the MonadThrow instance to raise a FailException in the underlying monad.

>>> throwFailT (failT "One thing went wrong")
*** Exception: FailException
"One thing went wrong"
...
>>> throwFailT (failT "One thing went wrong") :: Maybe ()
Nothing

Helpers

liftCatch :: (m (Either [e] a) -> (e -> m (Either [e] a)) -> m (Either [e] a)) -> FailT e m a -> (e -> FailT e m a) -> FailT e m a Source #

Lift a catchE operation to the new monad.

liftListen :: Monad m => (m (Either [e] a) -> m (Either [e] a, w)) -> FailT e m a -> FailT e m (a, w) Source #

Lift a listen operation to the new monad.

liftPass :: Monad m => (m (Either [e] a, w -> w) -> m (Either [e] a)) -> FailT e m (a, w -> w) -> FailT e m a Source #

Lift a pass operation to the new monad.