# MonadPlus reform proposal

The MonadPlus class is ambiguous: while all instances satisfy **Monoid** and **Left Zero**, some such as `[]` satisfy **Left Distribution**, while others such as `Maybe` and `IO` satisfy **Left Catch**.

## Proposal

It is proposed that MonadPlus be split like this:

### MonadZero

```
class Monad m => MonadZero m where
mzero :: m a
```

satisfying **Left Zero**:

```
mzero >>= k = mzero
```

### MonadPlus

```
class MonadZero m => MonadPlus m where
mplus :: m a -> m a -> m a
```

satisfying **Monoid** and **Left Distribution**:

```
mplus mzero b = b
mplus a mzero = a
mplus (mplus a b) c = mplus a (mplus b c)
mplus a b >>= k = mplus (a >>= k) (b >>= k)
```

### MonadOr

```
class MonadZero m => MonadOr m where
morelse :: m a -> m a -> m a
```

satisfying **Monoid** and **Left Catch**:

```
morelse mzero b = b
morelse a mzero = a
morelse (morelse a b) c = morelse a (morelse b c)
morelse (return a) b = return a
```

## Instances of both

Some types could be made instances of both. For instance:

```
instance MonadOr [] where
morelse [] b = b
morelse a b = a
```

The left-biased implementation of mplus for the Maybe monad should be used as an implementation of morelse, but it is also possible to give an unbiased mplus for Maybe:

```
instance MonadPlus Maybe where
mplus (Just a) Nothing = Just a
mplus Nothing (Just a) = Just a
mplus _ _ = Nothing
instance MonadOr Maybe where
morelse (Just a) _ = Just a
morelse _ b = b
```

Question: But does this instance satisfy **Left Distribution**? If a = Just v1 and b = Just v2, **Left Distribution** implies that Nothing = mplus (k v1) (k v2), which isn't generally true — take for instance

```
v1 = 0
v2 = 1
f 0 = Just 0
f 1 = Nothing
```

Am I missing something? -- Blaisorblade

## Discussion

Given that Control.Applicative(Alternative) now defines a class which seems innately bound to **Left Catch**, at least in spirit, it seems to make sense to clean up MonadPlus such that all instances obey **Left Distribution**? --sclv

I'd actually suggest almost the opposite, that MonadPlus be dispensed with and merged into Monad. The (controversial) fail method looks no different than an mzero, except the string argument; indeed, so far as I know `fail s` is just mzero for any MonadPlus. MonadPlus is also barely made use of; just guard and msum in the standard? To be concrete, I would make the following the default definitions (in Monad):

```
mzero = fail "something"
mplus a b = a
```

These are thus somewhat trivial by default, but having msum=head and guard=assert (roughly; more like `(`assert` return ())`) for less-flexible monads doesn't seem actually wrong and could be useful fallbacks.

I also question the claim that Maybe and IO should be thought of as "left catch". IO is not even in MonadPlus, and I don't see how it can be meaningfully in any way other than the above. Maybe does satisfy Left Catch, but it seems almost like that's only because it's such a simple monad (holding only one value). It is a useful observation that it fails Left Distribution, but that may only call for weaker Monad/Plus conditions.

The MonadOr idea is a solid one, but it seems to be taking the monad in a different direction. So if there's a good match in Control.Applicative or Parsec, that might be the best place to develop that idea. -- Galen

The default `mplus`

doesn't satisfy `mplus mzero b = b`

, so you lose Monoid which seems to be the only thing people actually agree on :) -- Benmachine