
OK, so I feel I understand monads fine. I regularly use Maybe, [] and IO, and I've even constructed a few monads of my own. But here's a question: what is the purpose of the MonadPlus class? Clearly it defines a binary operation over monadic values and an identity element for that operation. But... what is this supposed to *do*? (For example, (>>) has an almost identical signature to mplus. But presumably they don't both do the same thing...) What functionallity is this supposed to give you? [In a somewhat unrelated question... I saw some code the other day that used Either as if it were a monad. And yet, I don't see an instance given in the standard libraries - even though there should be one. I can see Functor (Either a), but not Monad (Either a) or even Monad (Either String)...]

On Fri, May 09, 2008 at 08:39:38PM +0100, Andrew Coppin wrote:
OK, so I feel I understand monads fine. I regularly use Maybe, [] and IO, and I've even constructed a few monads of my own. But here's a question: what is the purpose of the MonadPlus class?
Clearly it defines a binary operation over monadic values and an identity element for that operation. But... what is this supposed to *do*? (For example, (>>) has an almost identical signature to mplus. But presumably they don't both do the same thing...) What functionallity is this supposed to give you?
MonadPlus is a crude way of achieving the catching of exceptional cases, and you should think of mplus as being equivalent to (catch . const). The trouble is that MonadPlus doesn't provide any mechanism for finding out what went wrong, so I've only ever found it useful when using the Maybe monad (which itself has no way of identifying what went wrong).
[In a somewhat unrelated question... I saw some code the other day that used Either as if it were a monad. And yet, I don't see an instance given in the standard libraries - even though there should be one. I can see Functor (Either a), but not Monad (Either a) or even Monad (Either String)...]
I am pretty certain that there is a monad instance for Either, but also don't know where it's defined. -- David Roundy Department of Physics Oregon State University

On Fri, 2008-05-09 at 12:47 -0700, David Roundy wrote:
On Fri, May 09, 2008 at 08:39:38PM +0100, Andrew Coppin wrote:
OK, so I feel I understand monads fine. I regularly use Maybe, [] and IO, and I've even constructed a few monads of my own. But here's a question: what is the purpose of the MonadPlus class?
Clearly it defines a binary operation over monadic values and an identity element for that operation. But... what is this supposed to *do*? (For example, (>>) has an almost identical signature to mplus. But presumably they don't both do the same thing...) What functionallity is this supposed to give you?
MonadPlus is a crude way of achieving the catching of exceptional cases, and you should think of mplus as being equivalent to (catch . const). The trouble is that MonadPlus doesn't provide any mechanism for finding out what went wrong, so I've only ever found it useful when using the Maybe monad (which itself has no way of identifying what went wrong).
MonadPlus is a crude way of doing that, but that isn't the motivating example of MonadPlus, indeed, that arguably shouldn't be a MonadPlus instance. Cale Gibbard suggests (perhaps not originally) splitting MonadPlus into MonadPlus (and MonadZero) and MonadOrElse. They'd have essentially the same operations, but would be intended to satisfy different laws. Maybe, Either e, IO are better instances of MonadOrElse while [], Parser, LogicT, other non-determinism, parser, or concurrency monads would more appropriately be MonadPlus.

On Fri, May 9, 2008 at 2:39 PM, Andrew Coppin
[In a somewhat unrelated question... I saw some code the other day that used Either as if it were a monad. And yet, I don't see an instance given in the standard libraries - even though there should be one. I can see Functor (Either a), but not Monad (Either a) or even Monad (Either String)...]
It's used in the Error Monad. -- Rich JID: rich@neswold.homeunix.net LOI: https://www.google.com/reader/shared/00900594587109808626

Andrew Coppin wrote:
But here's a question: what is the purpose of the MonadPlus class?
It gives you a way of working with monads as monoids. Consider a Parsec example: metasyntactic = text "foo" `mplus` text "bar" `mplus` text "baz" You'll get back whichever one matched, in left-to-right-order, or mzero (a parse failure) if all of them fail.

Bryan O'Sullivan wrote:
Andrew Coppin wrote:
But here's a question: what is the purpose of the MonadPlus class?
It gives you a way of working with monads as monoids. Consider a Parsec example:
metasyntactic = text "foo" `mplus` text "bar" `mplus` text "baz"
You'll get back whichever one matched, in left-to-right-order, or mzero (a parse failure) if all of them fail.
...so it's a kind of choice operator? Run all actions until you get to one that succeeds and return the result from that?

On May 9, 2008, at 15:56 , Andrew Coppin wrote:
Bryan O'Sullivan wrote:
Andrew Coppin wrote:
But here's a question: what is the purpose of the MonadPlus class?
It gives you a way of working with monads as monoids. Consider a Parsec example:
metasyntactic = text "foo" `mplus` text "bar" `mplus` text "baz"
You'll get back whichever one matched, in left-to-right-order, or mzero (a parse failure) if all of them fail.
...so it's a kind of choice operator? Run all actions until you get to one that succeeds and return the result from that?
In monadic guise that's how it's usually used, yes (since monoids like (+) are not generally all that useful as monads; (++) (list monad) and (.) (Monad ((-) r)) might be, though). -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Andrew Coppin wrote:
...so it's a kind of choice operator? Run all actions until you get to one that succeeds and return the result from that?
In the context of Parsec, yes. In the grander scheme of things, the behaviour depends on whatever is appropriate for the particular monad you're working in. So, for example, mplus for lists is (++) and mzero is [], which is quite a different set of behaviours from the Parsec case. Usually, you can rely on MonadPlus behaving like a monoid. There are occasional exceptions, which is a mite upsetting. http://www.haskell.org/haskellwiki/MonadPlus

It sounds like the semantics of the MonadPlus methods are
under-specified. I recall once writing a newtype wrapper to treat the
same non-determinism monad with different mplus semantics, akin to cut
versus backtracking.
I think of MonadPlus as a less expressive version of msplit, from
Backtracking, Interleaving, and Terminating Monad Transformers
The Functional Pearl paper by Oleg Kiselyov, Chung-chieh Shan,
Daniel P. Friedman and Amr Sabry. ICFP 2005.
Is that an over-simplification?
On Fri, May 9, 2008 at 3:12 PM, Bryan O'Sullivan
Andrew Coppin wrote:
...so it's a kind of choice operator? Run all actions until you get to one that succeeds and return the result from that?
In the context of Parsec, yes. In the grander scheme of things, the behaviour depends on whatever is appropriate for the particular monad you're working in.
So, for example, mplus for lists is (++) and mzero is [], which is quite a different set of behaviours from the Parsec case. Usually, you can rely on MonadPlus behaving like a monoid. There are occasional exceptions, which is a mite upsetting.
http://www.haskell.org/haskellwiki/MonadPlus
http://www.haskell.org/mailman/listinfo/haskell-cafe

Andrew asked,
...so it's a kind of choice operator? Run all actions until you get to one that succeeds and return the result from that?
The eternal bit of trickiness for Haskell is that type classes group often together things that people don't immediately see as similar - monads probably being the best example. So it's probably best not to immediately try to find an all-encompassing summary of MonadPlus like "a kind of choice operator" but instead concentrate on the definition. The key thing is the line
mplus :: m a -> m a -> m a
You can combine two m a's together with a binary operation to get another m a. Absolutely any binary operation (with an identity) that fits the rather lax laws that come with MonadPlus will do. Depending on context mplus might mean "either/or", or "and", or "this first, or else that" or something entirely different that nobody here has anticipated yet. For each monad m, just try to think about how you might combine a pair of m a's and what might serve as an identity. -- Dan

On 10 May 2008, at 00:43, Dan Piponi wrote:
Andrew asked,
...so it's a kind of choice operator? Run all actions until you get to one that succeeds and return the result from that?
The eternal bit of trickiness for Haskell is that type classes group often together things that people don't immediately see as similar - monads probably being the best example.
Well, that's the whole point of mathematics, isn't it? Mathematics is just a way to name different things with one word (opposed to philosophy, which is a way to name the same thing with different words).

Miguel said:
Well, that's the whole point of mathematics, isn't it?
Abstraction is common to mathematics and computing. But in computing the abstraction often follows lines that seem obvious. For example a GUI library might have a Widget class and people can immediately identify various regions of the screen with Widgets and know that when they want a new kind of device in their GUI it's time to define a widget. Although the Widget class may be technically defined by the interface it exposes, in practice people just think "a gadget that can appear on the screen". Even someone who has never programmed can probably quickly guess what kinds of things correspond to instances of the Widget class. But mathematics is full of abstractions that aren't like this. Times modulo 24 hours and the way a closed loop can travel around a knot both form a group. The thing they have in common is that there's a binary operation with identity and inverses. Sometimes it can be more confusing to try to find a snappy English phrase that sums them up without restating the definition. Many common Haskell type classes lean towards the latter kind of abstraction. -- Dan

On Fri, 2008-05-09 at 12:48 -0700, Bryan O'Sullivan wrote:
Andrew Coppin wrote:
But here's a question: what is the purpose of the MonadPlus class?
It gives you a way of working with monads as monoids.
I find this description mostly useless. Monads form monoids without being MonadPlus. instance Monad m => Monoid (m ()) where mempty = return () mappend = (<<) You can form monoids out of Kleisli arrows, instance Monad m => Monoid (a -> m a) where mempty = return mappend = (<=<) You could form monads into a monoid in another way, instance (Monad m, Monoid a) => Monoid (m a) mempty = return mempty mappend = liftM2 mappend So "It gives you a way of working with monads as monoids." is significantly underspecified and doesn't actually say what MonadPlus means, let alone what it is intended for. A more interesting statement in that vein is: It gives you a way of working with monads as (distributive) near-rigs. This statement does actually encode some (all?) of the intended meaning of MonadPlus, e.g. mzero is intended to be a zero of (>>) beyond simply being a unit for mplus.
participants (9)
-
Andrew Coppin
-
Brandon S. Allbery KF8NH
-
Bryan O'Sullivan
-
Dan Piponi
-
David Roundy
-
Derek Elkins
-
Miguel Mitrofanov
-
Nicolas Frisby
-
Rich Neswold