MonadFail proposal (MFP): Moving fail out of Monad

David Turner dct25-561bs at
Thu Jun 11 15:23:28 UTC 2015

AIUI the point about ⊥ and (⊥, ⊥) being different doesn't matter here:
a bind for a single-constructor datatype never desugars in a way that
uses fail (which isn't to say that it can't be undefined)

For instance:

runErrorT (do { (_,_) <- return undefined; return () } :: ErrorT String IO ())

throws an exception, even though the bind is in ErrorT where fail just
returns left:

runErrorT (do { fail "oops"; return () } :: ErrorT String IO ())

=> Left "oops"

Hope that helps, and hope I understand correctly!


On 11 June 2015 at 16:08, Wolfgang Jeltsch <g9ks157k at> wrote:
> Hi David,
> thank you very much for this proposal. I think having fail in Monad is
> just plain wrong, and I am therefore very happy to see it being moved
> out.
> I have some remarks, though:
>> A class of patterns that are conditionally failable are `newtype`s,
>> and single constructor `data` types, which are unfailable by
>> themselves, but may fail if matching on their fields is done with
>> failable paterns.
> The part about single-constructor data types is not true. A
> single-constructor data type has a value ⊥ that is different from
> applying the data constructor to ⊥’s. For example, ⊥ and (⊥, ⊥) are two
> different values. Matching ⊥ against the pattern (_, _) fails, matching
> (⊥, ⊥) against (_, _) succeeds. So single-constructor data types are not
> different from all other data types in this respect. The dividing line
> really runs between data types and newtypes. So only matches against
> patterns C p where C is a newtype constructor and p is unfailable should
> be considered unfailable.
>>   - Applicative `do` notation is coming sooner or later, `fail` might
>>     be useful in this more general scenario. Due to the AMP, it is
>>     trivial to change the `MonadFail` superclass to `Applicative`
>>     later. (The name will be a bit misleading, but it's a very small
>>     price to pay.)
> I think it would be very misleading having a MonadFail class that might
> have instances that are not monads, and that this is a price we should
> not pay. So we should not name the class MonadFail. Maybe, Fail would be
> a good name.
>> I think we should keep the `Monad` superclass for three main reasons:
>>   - We don't want to see `(Monad m, MonadFail m) =>` all over the place.
> But exactly this will happen if we change the superclass of (Monad)Fail
> from Monad to Applicative. So it might be better to impose a more
> light-weight constraint in the first place. Functor m might be a good
> choice.
> All the best,
> Wolfgang
> _______________________________________________
> ghc-devs mailing list
> ghc-devs at

More information about the ghc-devs mailing list