`MonadFail`

This page contains some notes and ideas that predate the official **MonadFail Proposal (MFP)** which can be found at

## The Basic Idea

The basic idea is to split the `Monad`

class into

class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b m >> k = m >>= \_ -> k return :: a -> m a -- still in Monad for historic reasons return = pure class Monad m => MonadFail m where fail :: String -> m a

and adapt `do`

-desugaring accordingly.
See https://github.com/quchen/articles/blob/master/monad_fail.md for more details.

### Misc Ideas

To aid transition, we can keep `fail`

in `Monad`

, and start out with

class Monad m => MonadFail m where mfail :: String -> m a

(or maybe even require `MonadPlus`

, as `fail _ = mzero`

is a sensible default). This is a comparable situation as with post-AMP `pure`

/`return`

, where the now redundant `return`

(which is now an alias for `pure`

) is to be phased out into an ordinary top-level (non-method) function in the long term.

The `MonadFail(mfail)`

desugaring of `do`

could then be enabled via a language pragma `{-# LANGUAGE MonadFail -#}`

, allowing for have a future `-XHaskell201x`

to switch that feature on by default, while retaining `-XHaskell2010`

with the current old `Monad(fail)`

desugaring semantics.

`Monad(fail)`

could default to `MonadFail(mfail)`

via `-XDefaultSignatures`

## History

In Haskell 1.4 (postscript) `fail`

was not part of the `Monad`

class. Instead there was a separate `MonadZero`

class containing the `zero`

operation whose purpose was to handle pattern-failures in `do`

-syntax (akin to what `fail`

does today). Here are the original Haskell 1.4 class definitions quoted from section "6.2.5 Monadic Classes":

class Functor f where map :: (a -> b) -> (f a -> f b) class Monad m where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b return :: a -> m a class (Monad m) => MonadZero m where zero :: m a class (MonadZero m) => MonadPlus m where (++) :: m a -> m a -> m a

However, when Haskell 98 was drafted issues with irrefutable patterns lead to `MonadZero`

being folded into the `Monad`

class (but it doesn't seem to have been an unanimous nor easy decision back then).

The issue is highlighted by deconstructing a monadic action returning a single-constructor value:

f :: Monad m => m (a,b) -> m a f m1 = do { x <- m1; return (fst x) } g :: ??? m => m (a,b) -> m a g m1 = do { (a,_) <- m1; return a } h :: Monad m => m (a,b) -> m a h m1 = do { ~(a,_) <- m1; return a }

Should `???`

for `g`

be `Monad`

or `MonadZero`

? The single-constructor pattern match will never fail ("unfailable"), so `zero`

is never used. In fact, in Haskell 1.4 `g`

would only require `Monad`

, but requires the concept of `"unfailable" pattern matches (in addition to "irrefutable" pattern matches).