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).
3
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:
mplus
combines all possible results from both its arguments (satisfies Left Distribution law).[]
andSeq
are probably the only instances with this behavior.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 areMaybe
,Either
,STM
andIO
.
(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.
4