MonadPlus reform proposal
From HaskellWiki
(more discussion) |
(→Instances of both) |
||
| (2 intermediate revisions not shown.) | |||
| Line 58: | Line 58: | ||
morelse [] b = b | morelse [] b = b | ||
morelse a b = a | morelse a b = a | ||
| + | </haskell> | ||
| + | |||
| + | 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: | ||
| + | |||
| + | <haskell> | ||
| + | instance MonadPlus Maybe where | ||
| + | mplus (Just a) Nothing = a | ||
| + | mplus Nothing (Just a) = a | ||
| + | mplus _ _ = Nothing | ||
| + | |||
| + | instance MonadOr Maybe where | ||
| + | morelse (Just a) _ = Just a | ||
| + | morelse _ b = b | ||
</haskell> | </haskell> | ||
| Line 76: | Line 89: | ||
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 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 <hask>mplus</hask> doesn't satisfy <hask>mplus mzero b = b</hask>, so you lose Monoid which seems to be the only thing people actually agree on :) -- [[User:Benmachine|Benmachine]] | ||
[[Category:Proposals]] [[Category:Monad]] | [[Category:Proposals]] [[Category:Monad]] | ||
Current revision
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.
Contents |
1 Proposal
It is proposed that MonadPlus be split like this:
1.1 MonadZero
class Monad m => MonadZero m where mzero :: m a
satisfying Left Zero:
mzero >>= k = mzero
1.2 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)
1.3 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
2 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 = a mplus Nothing (Just a) = a mplus _ _ = Nothing instance MonadOr Maybe where morelse (Just a) _ = Just a morelse _ b = b
3 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