Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In the error monad, the first failure halts any execution further just carrying the fault through any following binds.

What monad halts on success only carrying forward successes, and basically swallowing any faults and trying the next bind disregarding the failure of the previous one?

The error monad could maybe be used for this treating failure like success, but I'm curious if the default libraries have a monad for this specific purpose, almost like an Or monad in my mind "Do this, or that"

Edit:

Behaviour would be:

Left "fail" >>= (\x -> Right "win") >>= (\x -> Left "ahh neener") >>= (\x -> Right (x + " yay"))

In the error monad the first left value is just carried forward, so the result of that is Left "fail". The behaviour I want is where the above returns Right "win yay" it's a trivial monad to implement I could write myself, but figured something existed to do such (maybe not using Either, but that's the first thing that comes to mind for such behaviour).

share|improve this question
    
Why the downvote? Is there something bad about this question? –  Jimmy Hoffa Jan 20 '13 at 5:33
    
Could you provide a small code snippet to show what your thinking? –  jozefg Jan 20 '13 at 9:13
    
Could it be that you are thinking of backtracking? –  scarfridge Jan 20 '13 at 10:48
add comment

1 Answer

up vote 3 down vote accepted

What you need is MonadPlus (see also Haskell wiki). It defines

mzero :: m a

which represents an unspecified error, and

mplus :: m a -> m a -> m a

which tries the second computation, if the first one fails. A few auxiliary functions are provided too:

-- Extends `mplus` to lists of computations:
msum :: MonadPlus m => [m a] -> m a
-- Fails a computation conditionally.
guard :: MonadPlus m => Bool -> m ()
-- Filter (fail) computations that don't satisfy the predicate.
mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a

Instances of MonadPlus can be divided into two categories:

  1. mplus combines all possible results from both its arguments (satisfies Left Distribution law). [] and Seq are probably the only instances with this behavior.
  2. mplus selects the left argument, if it contains a valid value, otherwise it selects the right one (satisfies Left Catch law). Instances with this behavior are Maybe, Either, STM and IO.

(MonadPlus instance of Either used to be defined in Control.Monad.Error as

instance (Error e) => MonadPlus (Either e) where
    mzero            = Left noMsg
    Left _ `mplus` n = n
    m      `mplus` _ = m

but for some reason it seems to be missing in the current version.)

See also MonadPlus on Wikibooks and MonadPlus definition for Haskell IO.

share|improve this answer
    
Thanks, sounds like monadplus list is the thought I had. –  Jimmy Hoffa Jan 20 '13 at 13:35
    
@JimmyHoffa I forgot to mention that Seq is also an instance of MonadPlus. I'd strongly recommend it over [], because concatenation (mplus) for Seq is O(log n) whereas concatenation of lists is O(n). –  Petr Pudlák Jan 20 '13 at 13:46
    
Cool, thanks for the tip! –  Jimmy Hoffa Jan 20 '13 at 14:47
    
The haskell wiki is very illuminating, sounds like the haskell community is pondering which way it should go in the same way I'm pondering which way I want it to work; whether I want it to be an Or as a "This or that" or a then, "This then that" where the first one failing causes behaviour like Or using the pre-failure value for the next one, but a success still calls the next one unlike Or and uses the value returned from the first function. –  Jimmy Hoffa Jan 22 '13 at 17:34
    
Yes, I support the MonadPlus reform proposal, I believe this would clarify things a lot. –  Petr Pudlák Jan 22 '13 at 18:07
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.