failable

A 'Failable' error monad class to unify failure across monads that can fail

Version on this page:0.1.1.0@rev:1
LTS Haskell 21.25:1.2.4.0
Stackage Nightly 2023-06-21:1.2.4.0
Latest on Hackage:1.2.4.0

See all snapshots failable appears in

BSD-3-Clause licensed by Erick Gonzalez
Maintained by [email protected]
This version can be pinned in stack with:failable-0.1.1.0@sha256:ff1a9352a1459b9791f0cb3f7f1c225318cffb684a6aec09f1cd637904112515,1557

Module documentation for 0.1.1.0

Depends on 3 packages(full list with versions):

Control.Monad.Failable

Yet another “error” handling monad (class)

This library provides a ‘Failable’ error monad class to unify failure across monads and transformers most commonly used to implement pipelines that can fail.

But.. don’t we have ‘MonadFail’, ‘MonadThrow’, ‘MonadError’,.. and the true haskeller should be using ‘Alternative’ anyway!

I am sure a lot of ink has been spilled in forums and around water coolers all around the world, debating the merits and fallacies of one approach or the other. The reason for this package is not to participate in this discussion but rather to provide a simple no nonsense means of signaling a computation “failure” in those monads that provide the inherent means to do so, and to do it in a consistent manner

Usage


data FooError = NotImplemented deriving (Typeable, Show)

instance Exception FooError

foo :: (Failable m) => m Int
foo = failure NotImplemented

Now, if one called foo in a Maybe monad:

> foo :: Maybe Int
> Nothing

the failure is then conveyed by returning Nothing as per definition of the Maybe monad. Now in the case of the Either SomeException monad:

> foo :: Either SomeException Int
> Left NotImplemented

but what if we are working in the IO monad?

> foo :: IO Int
> * * * Exception: NotImplemented

In this case, the failure can only be conveyed by throwing an IO exception.

Now, the point where Failable diverges from say MonadThrow for example is when it comes to monad transformers. For example:

> runMaybeT foo :: IO (Maybe Int)

Would throw an Exception: NotImplemented if it was implemented in a MonadThrow context. Since the reason d’etre for the runMaybeT is to provide the underlying monad (transformer) with Maybe like behaviour, i.e. have Nothing be returned in case of aborting the Maybe pipeline so to speak, then throwing an exception defeats IMHO the purpose of using MaybeT in the first place. So, in the case of Failable:

> runMaybeT foo :: IO (Maybe Int)
> Nothing

And the same thing applies to runExceptT etc.

Changes

Changelog for failable

Unreleased changes