haskell - 为什么 monad 类型类中应该存在 fail 方法?

标签 haskell pattern-matching monads do-notation

所以我有这行代码:

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

这当然会给出异常,因为该模式不匹配 Nothing。

另一方面,这段代码给出了不同的结果,[]:
do
  Just x <- [Nothing]
  return x

在我看来,它们应该产生相同的结果,因为应该将 do-blocks 脱糖为使用 (>>=) 并返回。但事实并非如此,使 do-notation 成为一个特性而不是一个语法糖。

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

所以我的问题是 - 为什么要存在 fail 方法?

最佳答案

代码如

\(Just x) -> ...

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

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

选择是好是坏可能是有争议的。只是为了展示另一个设计选项,Monad没有 fail 也可以设计类, 和块如
do ... 
   Just x <- ...
   ...

可能被禁止,或要求特殊MonadFail Monad 的子类。出错也是一种选择,但我们喜欢写例如
catMaybes xs = do Just x <- xs
                  return x
-- or
catMaybes xs = [ x | Just x <- xs ]

丢弃 Nothing s 来自列表。

关于haskell - 为什么 monad 类型类中应该存在 fail 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30545781/

相关文章:

haskell - 使用命令行参数运行我的程序

haskell - 是否可以在 lambda 表达式中使用无可辩驳的波浪号 (`~` ) 模式?

haskell - 如何使 MonadRandom 成为仿函数?

haskell - 在其他一些 monad m1 中绑定(bind)一个 Monadic 值 (m2 a)

haskell - 使用具有自定义数据类型的过滤器

haskell - 行动上的懒惰? ( haskell )

algorithm - 在 Haskell 中快速获取大小为 N 的所有子集

java - java中模式的字符串比较

.net - 与DataGridColumn.Visibility匹配的F#模式

scala - Kleisli Arrow with Writer in Scala。为什么不编译?