5

所以我有这行代码:

[Nothing] >>= \(Just x) -> [x]

这当然给出了例外,因为模式不匹配任何内容。

另一方面,这段代码给出了不同的结果,[]:

do
  Just x <- [Nothing]
  return x

正如我所看到的,它们应该产生相同的结果,因为应该将 do-blocks 减少为使用 (>>=) 并返回。但事实并非如此,使 do-notation 成为一种功能而不是语法糖。

我知道 monad 类型类中存在 fail 并且我知道当模式匹配在 do-block 中失败时会调用它,但我不明白为什么它是一种与使用普通 monad 操作不同的想要的行为。

所以我的问题是 - 为什么失败方法应该存在?

4

1 回答 1

2

代码如

\(Just x) -> ...

表示一个函数。只有一种方法可以使用这样的值:将其应用于某个参数。当所述参数与模式(例如 is )不匹配时,Nothing应用程序是不可能的,唯一的通用选项是引发运行时错误/异常。

相反,当在do-block 中时,我们有一个类型类:monad。理论上,此类可以扩展为此类情况提供行为。事实上,Haskell 的设计者决定fail为这种情况添加一个方法。

选择是好是坏是有争议的。只是为了呈现另一种设计选项,Monad该类可以在没有fail, 和块的情况下设计,例如

do ... 
   Just x <- ...
   ...

可能是被禁止的,或者要求一个特殊MonadFail的 Monad 子类。Erroring out 也是一种选择,但我们喜欢写 eg

catMaybes xs = do Just x <- xs
                  return x
-- or
catMaybes xs = [ x | Just x <- xs ]

从列表中丢弃Nothings。

于 2015-05-30T14:13:35.940 回答