
concat (map c (a ++ b)) = concat (map c a) ++ concat (Map c b),
which is easily seen to be true (if applying c to an element of a causes an error, neither side will go past that).
Daniel
So do we consider [] to be fail?, Monad.hs defines:
I will ignore "fail" if you don't mind. I can only think of it as a convenient hack. I'll get to failure later. If the monad represents a state then IMO mplus should be the most intuitive definition for the sum of two such states.
instance MonadPlus [] where mzero = [] mplus = (++)
On the list monad, I think of the mplus operation as the "union" two non-deterministic states. Mzero is the state that works as the identity (which is when you have no possible state at all). MonadPlus instances for Parsers are similar, p1 mplus p2 is a parser p that will return the concatenation of the [(a, string)] lists that would be returned by p1 and p2. The datatype Maybe, on the other hand, just allows us to keep at most one valid state. Summing "no state" with "some state" gives "some state", if we have two states, we get to keep the first. And all seems fine to me, and I haven't mentioned failure.
What would happen if this was the definition?
instance MonadPlus [] where mzero = [] mplus a b
| a == [] = b | otherwise = a
Then, I'd say you're not thinking of monadic sums, but of catching errors, and the appropriate place for that is the class MonadError. Such a function can easily be written in terms of catchError. It seems quite useful, so it would probably make a good method with default instance: skipError x y = catchError x (\_->y) And of course we need MonadError instances for Maybe and Lists. instance MonadError () Maybe where throwError _ = Nothing Nothing `catchError` h = h () jx `catchError` _ = jx instance MonadError () [] where throwError _ = [] [] `catchError` h = h () xs `catchError` _ = xs The Maybe datatype is used to model computation errors all the time, so I never understood why its MonadError instance was not provided. The List instance seems pretty fair too. And there you have, skipError [1,2] [] = [1,2] skipError [] [1,2] = [1,2] skipError [1,2] [3,4] = [1,2] J.A.