2015-05-30 44 views
4

所以我有这行代码:monad类型中为什么应该有失败方法?

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

当然这给了异常,因为模式不匹配没什么。

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

do 
    Just x <- [Nothing] 
    return x 

在我看来,他们应该产生相同的结果,因为做块应该被脱到使用(>> =)并返回。但事实并非如此,使得符号是一个特征而不是语法糖。

我知道单子类型类中存在失败,并且我知道当模式匹配在do-block中失败时会调用它,但我无法理解为什么它是一种想要的行为,应该与使用不同正常的monad操作。

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

+4

它仍然是句法糖,糖只比你想象的要甜一点点。 –

+0

如果它真的是一个语法糖,那么它将如何被用于绑定和返回呢? – Brrch

+1

[Haskell报告](https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.14)对此有确切答案。 –

回答

1

代码如

\(Just x) -> ... 

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

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

选择是好还是坏可以引起争议。只是呈现另一种设计选项,Monad类可以被设计成没有fail,并阻止诸如

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

可能已被禁止,或作出需要特殊的MonadFail子单子。错误输出也是一种选择,但我们喜欢编写例如

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

从列表中丢弃Nothing s。

+0

还有一种可能性,即使超出'do'表示法:使所有模式匹配我们无法证明终止隐式结束'_ - > patternMatchFail“行号”'然后使'类PatternMatchFailable pmf其中patternMatchFail: :字符串 - > pmf'。任何不属于该类的东西都会被视为编译器错误。 (请注意,它是*输出*类型,而不是输入类型,它表示模式匹配是否会失败。) –

+0

我不明白为什么它应该有不同的行为。 – Brrch

+1

@ChrisDrost这会破坏引用透明性(以同样的方式,使用'fail'的当前转换令人遗憾的是'Monad'的特定实现已经做到了这一点):内联定义将以程序内可观察的方式改变行号。 –

相关问题