所以我有这行代码:
[Nothing] >>= \(Just x) -> [x]
当然会给出异常,因为该模式与Nothing不匹配。
另一方面,此代码给出了不同的结果,[]:
do
Just x <- [Nothing]
return x
在我看来,它们应该产生相同的结果,因为do-blocks应该被用于使用(&gt;&gt; =)并返回。但实际情况并非如此,使得注释成为一种特征,而不是语法糖。
我知道monad类型类中存在失败,我知道在do-block中模式匹配失败时会调用它,但我不能理解为什么它是一个想要的行为应该不同于使用正常的monad操作。
所以我的问题是 - 为什么要存在失败方法?
答案 0 :(得分:1)
代码如
\(Just x) -> ...
表示功能。只有一种方法可以使用这样的值:将它应用于某个参数。当所述参数与模式不匹配(例如Nothing
)时,应用程序是不可能的,并且唯一的通用选项是引发运行时错误/异常。
相反,当在do
- 块中时,我们有一个类型类:monad。从理论上讲,这类课程可以扩展到为这种情况提供行为。实际上,Haskell的设计者决定为这种情况添加fail
方法。
选择是好还是坏都可能引起争议。只是为了呈现另一个设计选项,Monad
类可以设计为没有fail
,而像
do ...
Just x <- ...
...
可能被禁止,或者需要Monad的特殊MonadFail
子类。错误输出也是一种选择,但我们喜欢写例如。
catMaybes xs = do Just x <- xs
return x
-- or
catMaybes xs = [ x | Just x <- xs ]
从列表中删除Nothing
。