Haskell和Erlang中的模式匹配

Ral*_*lli 6 erlang haskell pattern-matching

我有一个小的Erlang函数,比较两个列表是否相等:

myEq([], [])         -> true;
myEq([X|Xs], [X|Ys]) -> myEq(Xs, Ys);
myEq(_, _)           -> false.
Run Code Online (Sandbox Code Playgroud)

比较发生在第2行中,X[X|Xs]总结合到第一列表的第一元件,所述[X|Ys]匹配项只有当这两个列表的第一元素是相等的.

如果我在Haskell中尝试这个,我会收到一条错误消息:" 冲突的定义x ".Haskell中可能的解决方案是:

myEq (x:xs) (y:ys) = if x == y then myEq xs ys else False
Run Code Online (Sandbox Code Playgroud)

但我想知道是否可以使用模式匹配在Haskell中执行此操作?

Wil*_*sem 10

不,在Haskell中,您不能x在子句的头部使用相同的变量.哈斯克尔并没有统一相等检查例如像分别序言二郎做.这在Haskell '98报告中指定:

对应于每个匹配的模式集必须是线性的 - 不允许变量在整个集合中出现多次.

(复制,粗体添加)

唯一的方法是使用警卫(或当然体内任何其他类型的检查).但是你可以写得更优雅,如:

myEq [] [] = True
myEq (x:xs) (y:ys) | x == y = myEq xs ys
--                 | otherwise = False
myEq _ _ = False
Run Code Online (Sandbox Code Playgroud)

otherwise由于Haskell将在最后一个子句上回退并因此返回,因此可以省略该情况False.

或者更优雅:

myEq [] [] = True
myEq (x:xs) (y:ys) = x == y && myEq xs ys
myEq _ _ = False
Run Code Online (Sandbox Code Playgroud)

我个人认为这更好,因为在这里你明确说明x等于y这样做错误就像意外写同一个变量不会发生.虽然当然这是一个品味问题.

  • 澄清一下:Erlang 也不做统一。如果一个变量在一个模式中多次出现,Erlang 编译器只是为其他出现的地方生成新的名称,并插入一个要求它们相等的保护测试,就像你在 Haskell 中手动做的那样。 (2认同)