14

如果我使用 case 语句将字符串文字与字符串文字进行比较,我会得到预期的行为:如果它们相同 - 它匹配,如果它们不匹配 - 它不匹配。

但是,如果我将字符串文字与作为字符串的常量进行比较,则会收到“模式匹配重叠”警告,并且具有常量的分支始终匹配。

这是一个示例会话:

Prelude> let var1 = "abc"
Prelude> let var2 = "def"
Prelude> case var1 of { var2 -> "Fail"; _ -> "Win" }

<interactive>:1:0:
    Warning: Pattern match(es) are overlapped
             In a case alternative: _ -> ...
"Fail"
Prelude> case "abc" of { var2 -> "Fail"; _ -> "Win" }

<interactive>:1:0:
    Warning: Pattern match(es) are overlapped
             In a case alternative: _ -> ...
"Fail"
Prelude> case "abc" of { "def" -> "Fail"; _ -> "Win" }
"Win"

同时,如果行为符合预期:

> Prelude> if var1 == var2 then "Fail" else "Win" 
"Win"

这里发生了什么?这种行为有什么意义?

4

3 回答 3

30

请参阅 Don 的答案以了解原因。做你想做的事情的一个常见习语是:

var1 = "abc"
var2 = "def"

foo x = case () of
    () | x == var1 -> "Fail"
       | x == var2 -> "Failzor"
       | otherwise -> "WIN"

当然,在这种情况下,我们会丢失case并且直接在函数上编写守卫:

foo x | x == var1 = "Fail"
      | ...

更新

这些天来,MultiWayIf扩展用稍微少一点的句法噪音来做到这一点。

{-# LANGUAGE MultiWayIf #-}

foo x = if | x == var1 -> "Fail"
           | x == var2 -> "Failzor"
           | otherwise -> "WIN"
于 2010-08-13T21:13:31.123 回答
22

Haskell 中的模式匹配绑定了新变量。所以当你写:

case x of
    y -> ...

您现在已将新变量“y”绑定到“x”的值。这是微不足道的“模式”。当涉及构造函数时,您可以更清楚地看到绑定是如何工作的:

case x of 
    (a, b) -> ...

现在 a 和 b 绑定到元组的组件。等等用于解构和绑定其他数据类型。因此,要匹配字符串文字,您可以编写:

case x of
    "def" -> ....
于 2010-08-13T17:27:34.797 回答
9

那是因为“案例”并没有按照您的想法进行。设置为“def”的“var2”没有与“var1”进行比较。相反,您将获得一个包含绑定到“var1”值的新“var2”的新范围。

错误消息的原因是,就编译器而言,“var2 -> ...”和“_ -> ...”之间没有区别。两者都匹配“var1”的所有可能值。

于 2010-08-13T17:05:42.227 回答