f x zero = Nothing
f x y = Just $ x / y
where zero = 0
文字绑定标识符zero
只是在警告Pattern match(es) are overlapped
之后匹配所有标识符。
答案 0 :(得分:6)
Haskell的语法是如何工作的; 模式中的每个小写 - 初始变量名称(重新)绑定该名称。任何现有绑定都将阴影。
但即使不是这种情况,第一种选择也不会看到zero
的绑定,因为Haskell的语法是如何工作的。类似的事情发生在以下版本中:
f = \v1 v2 -> case (v1, v2) of
(x, zero) -> Nothing
(x, y) -> Just $ x / y
where zero = 0
where
子句仅适用于 一个替代,而不是整个备选列表。该代码几乎与
f = \v1 v2 -> case (v1, v2) of
(x, zero) -> Nothing
(x, y) -> let zero = 0 in Just $ x / y
答案 1 :(得分:5)
如果绑定标识符在模式匹配中具有与未绑定标识符不同的语义,则可能非常容易出错,因为绑定新标识符可能会使标识符位于范围内的任何位置都会混乱。
例如,假设您正在导入某个模块Foo(不合格)。现在,由于某种原因,模块Foo被更改为添加绑定<input type="hidden" ng-model="dependentid" />
。现在在你的模式匹配中,你突然将第一个参数与42进行比较,而不是将其绑定到x = 42
。这很难找到错误。
因此,为了避免这种情况,标识符模式具有相同的语义,无论它们是否已经绑定到某处。
答案 2 :(得分:4)
因为它们非常脆弱。这算什么?
f x y z = 2*x + 3*y + z
您希望这等于
吗?f x 3 z = 2*x + 9 + z
f _ _ _ = error "non-exhaustive patterns!"
只是因为在同一个1000+线路模块中某处定义了y = 3
?
还要考虑这个:
import SomeLibrary
f x y z = 2*x + 3*y + z
如果将来的版本SomeLibrary
定义y
怎么办?我们不希望突然停止工作。
最后,如果Eq
没有y
个实例,该怎么办?
y :: a -> a
y = id
f :: a -> (a -> a) -> a
f x y = y x
f x w = w (w x)
当然,这是一个人为的例子,但运行时无法比较输入函数以检查它是否等于y
。
为了消除歧义,一些像Swift这样的新语言使用了两种不同的语法。例如。 (伪代码)
switch someValue {
case .a(x) : ... // compare by equality using the outer x
case .b(let x) : ... // redefine x as a new local variable, shadowing the outer one
}
答案 3 :(得分:2)
zero
只是一个在模式中出现的变量,就像y
在第二行中所做的那样。这两者没有区别。当一个变量出现在模式中时,会引入一个 new 变量。如果已经存在该变量的绑定,则新变量将隐藏旧变量。
因此,您无法在模式中使用已绑定的变量。相反,你应该做那样的事情:
f x y | y == zero = Nothing
where zero = 0
f x y = Just $ x / y
请注意,我还移动了where
子句,使其位于第一行的范围内。