为什么Haskell不相关模式匹配的绑定标识符?

sof*_*sof -1 haskell pattern-matching

f x zero = Nothing
f x y = Just $ x / y 
  where zero = 0 
Run Code Online (Sandbox Code Playgroud)

文字绑定标识符zero仅在警告后匹配所有标识符Pattern match(es) are overlapped.

小智 6

这就是Haskell的语法如何工作; 模式中的每个小写 - 初始变量名称(重新)绑定该名称.任何现有绑定都将被遮蔽.


但即使不是这种情况zero,由于Haskell的语法如何工作,第一个替代方案将无法看到绑定.类似的事情发生在以下版本中:

f = \v1 v2 -> case (v1, v2) of
                  (x, zero) -> Nothing
                  (x, y)    -> Just $ x / y
                    where zero = 0
Run Code Online (Sandbox Code Playgroud)

where条款仅适用于它所属的一个备选方案,而不适用于整个备选方案列表.那段代码几乎和它一样

f = \v1 v2 -> case (v1, v2) of
                  (x, zero) -> Nothing
                  (x, y)    -> let zero = 0 in Just $ x / y
Run Code Online (Sandbox Code Playgroud)


sep*_*p2k 5

如果绑定标识符在模式匹配中具有与未绑定标识符不同的语义,那么这可能非常容易出错,因为绑定新标识符可能会使标识符在范围内的任何位置混乱模式匹配.

例如,假设你要导入一些模块Foo(不合格).现在,x = 42由于某种原因,模块Foo被更改为添加绑定.现在在你的模式匹配中你突然将第一个参数与42进行比较而不是将其绑定到x.这是一个很难找到的bug.

因此,为了避免这种情况,标识符模式具有相同的语义,无论它们是否已经绑定到某处.


chi*_*chi 5

因为它们非常脆弱。这算什么呢?

f x y z = 2*x + 3*y + z
Run Code Online (Sandbox Code Playgroud)

您是否希望这等于

f x 3 z = 2*x + 9 + z
f _ _ _ = error "non-exhaustive patterns!"
Run Code Online (Sandbox Code Playgroud)

仅因为y = 3在同一1000+行模块中的某处有定义?

另外考虑一下:

import SomeLibrary
f x y z = 2*x + 3*y + z
Run Code Online (Sandbox Code Playgroud)

如果将来的版本中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)
Run Code Online (Sandbox Code Playgroud)

当然,这是一个人为的示例,但是运行库无法比较输入函数以检查其是否相等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
}
Run Code Online (Sandbox Code Playgroud)