Instance MonadPlus IO
is unique because mzero
throws:
Prelude Control.Monad> mzero
*** Exception: user error (mzero)
So accordingly, MonadPlus IO
implies that it is also intended for errors.
mzero
apparently serves as the identity element if the other action doesn't throw:
Prelude Control.Monad> mzero `mplus` return 0
0
Prelude Control.Monad> return 0 `mplus` mzero
0
But it doesn't when both actions throw:
Prelude Control.Monad> fail "Hello, world!" `mplus` mzero
*** Exception: user error (mzero)
Prelude Control.Monad> mzero `mplus` fail "Hello, world!"
*** Exception: user error (Hello, world!)
So MonadPlus IO
is not a monoid.
If it violates MonadPlus
laws when user intends errors, what is it actually intended for?
fail
is not intended as a general-purpose method to raise an error; it's an implementation detail for pattern-match failures indo
notation and list comprehensions. – Vatican