Brr*_*rch 5 monads haskell pattern-matching do-notation
所以我有这行代码:
[Nothing] >>= \(Just x) -> [x]
Run Code Online (Sandbox Code Playgroud)
这当然会产生异常,因为该模式与 Nothing 不匹配。
另一方面,这段代码给出了不同的结果,[]:
do
Just x <- [Nothing]
return x
Run Code Online (Sandbox Code Playgroud)
在我看来,它们应该产生相同的结果,因为 do 块应该被脱糖为使用 (>>=) 并返回。但事实并非如此,这使得 do 符号成为一种功能而不是语法糖。
我知道 monad 类型类中存在失败,并且我知道当 do 块中的模式匹配失败时会调用它,但我无法理解为什么它是一种需要的行为,应该与使用正常的 monad 操作不同。
所以我的问题是 - 为什么要存在失败方法?
代码如
\(Just x) -> ...
Run Code Online (Sandbox Code Playgroud)
表示一个函数。只有一种方法可以使用这样的值:将其应用于某个参数。当所述参数与模式不匹配(例如 is Nothing)时,应用程序是不可能的,唯一的通用选项是引发运行时错误/异常。
相反,当在do-block 中时,我们有一个类型类:一个 monad。从理论上讲,此类可以扩展为此类情况提供行为。事实上,Haskell 的设计者决定fail为这种情况添加一个方法。
这个选择是好还是坏可能会引起争议。只是为了提供另一种设计选项,该类Monad的设计可以没有fail, 和诸如
do ...
Just x <- ...
...
Run Code Online (Sandbox Code Playgroud)
可能会被禁止,或者需要MonadFailMonad 的特殊子类。错误也是一种选择,但我们喜欢写例如
catMaybes xs = do Just x <- xs
return x
-- or
catMaybes xs = [ x | Just x <- xs ]
Run Code Online (Sandbox Code Playgroud)
Nothing从列表中丢弃s。