
Hello,
On Sun, 27 Mar 2005 04:32:37 +0200, Yitzchak Gale
Yes, that would be nice. But I am suggesting this as a bug fix. This is a serious problem that makes it very awkward to handle a very common case. I am hoping for a fix that does not break currently non-broken programs.
Here are two ways to fix it:
1. The bold approach: o Remove the implementation of fail in Monad Either o Remove the Error instance requirement o Possibly move the Monad Either instance to a different module, and just import it in Control.Monad.Error
That implies that code using fail instead of throwError to throw an Error or, worse yet, implicitly throwing an Error with a failed pattern match, would be considered already broken. This would have been the right thing to do in the first place (assuming no additional compiler support that allowed a sane pattern matching even if fail was method of a class MonadZero, see below), but is inacceptable as a library change. It would silently change the meaning of existing code, and porting from the old to the new behaviour would be very unreliable if you don't have test cases for each error condition imaginable.
2. The less bold but messier approach: Add a new monad to the standard library that looks just like Either, for non-Error calculations that need to exit with a value. Of course, if we had two such monads, one would expect Either to be the one without an (Error e) constraint, but this definitely sounds like the lesser of two evils.
3. Compiler support. Again, this would break existing code (but at least porting is straightforward) and Haskell 98 compatibility, so consider it as a suggestion for Haskell 2. Not all monads support failure, so it is natural to put the fail method in an additional class MonadZero/MonadFail.
class Monad m => MonadFail m where fail :: String -> m a As "x <- m" is very common in do-notation, the translation from the report now requires a MonadFail constraint (btw, this is exactly what happens when we use the above MonadFail class in do-notation in ghc under -fno-implicit-prelude).
do x <- m; rest ==> m >>= \x -> do rest ,
If the compiler only used the translation from the report if the pattern matching was non-exhaustive and in all other cases the more straightforward translation the Monad instances of Either could simply be
instance Monad (Either e) instance Error e => MonadFail (Either e) .
Thomas