(un-)deprecation of Control.Monad.Error

Paterson, Ross R.Paterson at city.ac.uk
Mon Oct 29 16:40:28 UTC 2018


On Sat, Oct 27, 2018 at 03:53:48PM +0200, Bertram Felgenhauer via Libraries wrote:
> I'm unhappy about the current state of Control.Monad.Error; the module
> is deprecated, stating:
> 
>     Module ‘Control.Monad.Error’ is deprecated:
>       Use "Control.Monad.Except" instead
> 
> However, Control.Monad.Except implements 'fail' as an error, inheriting
> the behavior of Identity. To my mind the whole point of
> Control.Monad.Error is that it replicates the old non-error behavior of
> `fail` that the Either type and EitherT used to have.

I think that fail on Either or EitherT has always been the default (error).

> The situation is similar with the MonadFail class; there is are
> 
>   instance (Monad m, Error e) => MonadFail (ErrorT e m)
> 
> and
> 
>   instance MonadFail m => MonadFail (ExceptT e m)
> 
> which means that Except doesn't have a MonadFail instance,
> because Identity has none, whereas ErrorT implements a non-error
> version of `fail`.

The principal flaw of ErrorT is that the monad methods had constraints
on the exception type, even though they don't need them.  (A lesser
issue was that the naming was inconsistent with the other transformers.)

One possibility would be to change the MonadFail instance for ExceptT
to give the functionality of the ErrorT instance:

  instance (Monad m, Message e) => MonadFail (ExceptT e m)

(If it is decided in the other thread to have a non-default MonadFail
instance for Either, it would make sense to use that class here.)

Then, for base >= 4.9:
- there would be a MonadFail instance for ExceptT ... Identity
- the MonadFail instances for monads based on [], Maybe and IO would have
  the constraint on the exception type, and different behaviour.

That would be awkward, but seems preferable to having two very similar
but slightly different transformers.


More information about the Libraries mailing list