MonadFail proposal (MFP): Moving fail out of Monad

Henning Thielemann lemming at
Tue Jun 9 21:56:59 UTC 2015

now some details to the discussion:

On Tue, 9 Jun 2015, David Luposchainsky wrote:

> Here's a short abstract:
> - - Move `fail` from `Monad` into a new class `MonadFail`.

You think about making MonadFail a subclass of Applicative where the name 
MonadFail becomes misleading - how about naming it Fail instead?

> - - Remove the `String` argument? **No.** The `String` might help error reporting
>  and debugging. `String` may be ugly, but it's the de facto standard for
>  simple text in GHC. No high performance string operations are to be
>  expected with `fail`, so this breaking change would in no way be justified.
>  Also note that explicit `fail` calls would break if we removed the argument.

You know that I am concerned with a strict separation of programming 
errors and exceptions. "fail" is part of the confusion between the two 
concepts. If "fail" is inserted by the compiler as desugaring of a pattern 
match then it gets a compiler generated string as argument. This string 
refers to program details like source locations and constructor names that 
have no meaning for the program user. They are intended for debugging, 
they address the programmer. This implies that "fail" indicates a 
programming error. In contrast to that, in a monad like Maybe we want to 
convert a mismatching pattern to Nothing. The compiler generated argument 
to "fail" does not show up in the Nothing result. This usecase is clearly 
not for debugging but for regular use in a program. We only want to get 
the exceptional value Nothing.

We should clearly decide what "fail" is intended for - for programming 
errors or for exceptions. I guess that people want to use it in the second 
sense, e.g. something like "guard" driven by a pattern match in the Maybe 
or list monad. But then "fail" must not have an argument because what user 
related information can the compiler add automatically? Instead of 
removing the String argument from "fail", the compiler could simply call 
"mzero" instead. If we want to use "fail" for exceptions then it would be 
also ok for parser libraries to use it for parser failures. Nonetheless 
they might be better served with an Except-like monad where they can 
choose more specific types for the exception messages, e.g. parser errors 
with source location. In summary I think that the cleanest solution would 
be to phase out "fail" completely in the long run. But using "mzero" 
instead of "fail" for monadic pattern matches would alter the proposal 
considerably. Using "mzero" requires a monad with "mplus" and for support 
of monads with "mzero" but no "mplus" we need to split MonadPlus, too.

More information about the Libraries mailing list