MonadPlus IO
实例是独特的,因为 mzero
抛出异常:
Prelude Control.Monad> mzero
*** Exception: user error (mzero)
因此,MonadPlus IO
的使用意味着它也适用于错误处理。
mzero
看起来是一个标识元素,如果其他操作没有抛出异常:
Prelude Control.Monad> mzero `mplus` return 0
0
Prelude Control.Monad> return 0 `mplus` mzero
0
但是,当两个操作都抛出异常时,它就无法运行:
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!)
因此,MonadPlus IO
不是一个单子。
如果用户意图出错时违反了MonadPlus
法则,那它实际上是用于什么目的呢?
fail
不是用于引发错误的通用方法;它是do
表达式和列表推导中模式匹配失败的实现细节。 - chepner