简体   繁体   English

Haskell 中 case 语句中的模式匹配变量

[英]Pattern matching variables in a case statement in Haskell

If I compare a string literal to a string literal using the case statement, I get the expected behavior: if they are the same - it matches, if they are not - it does not.如果我使用 case 语句将字符串文字与字符串文字进行比较,我会得到预期的行为:如果它们相同 - 它匹配,如果它们不匹配 - 它不匹配。

However, if I compare a string literal to a constant that is a string, I get "Pattern matches are overlapped" warning and the branch with the constant always matches.但是,如果我将字符串文字与作为字符串的常量进行比较,我会收到“模式匹配重叠”警告,并且具有常量的分支始终匹配。

Here's an example session:这是一个示例会话:

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"

Meanwhile, if behaves as expected:同时,如果行为符合预期:

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

What's going on here?这里发生了什么? How does this behavior make sense?这种行为有何意义?

See Don's answer for why.请参阅 Don 的回答了解原因。 A common idiom for doing what you are trying to do is this:做你想做的事情的一个常见习惯是:

var1 = "abc"
var2 = "def"

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

Of course in this case we would lose the case and just write the guards directly on the function:当然在这种case下我们会失败,直接在函数上写守卫:

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

UPDATE更新

These days the MultiWayIf extension does this with slightly less syntactic noise.如今, MultiWayIf扩展以稍微少一点的句法干扰来实现这一点。

{-# LANGUAGE MultiWayIf #-}

foo x = if | x == var1 -> "Fail"
           | x == var2 -> "Failzor"
           | otherwise -> "WIN"

Pattern matching in Haskell binds new variables. Haskell 中的模式匹配绑定新变量。 So when you write:所以当你写:

case x of
    y -> ...

you have now bound a new variable 'y' to the value of 'x'.您现在已将新变量“y”绑定到“x”的值。 This is the trivial "pattern".这是琐碎的“模式”。 You can see more clearly how the binding works when a constructor is involved:当涉及构造函数时,您可以更清楚地看到绑定是如何工作的:

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

Now a and b bind to components of the tuple.现在 a 和 b 绑定到元组的组件。 And so on for deconstructing and binding other data types.等等用于解构和绑定其他数据类型。 Thus, to match a string literal, you would write:因此,要匹配字符串文字,您可以这样写:

case x of
    "def" -> ....

That's because the "case" isn't doing what you think it is.那是因为“案例”并没有按照您的想法进行。 The "var2" that was set to "def" is not being compared with "var1".未将设置为“def”的“var2”与“var1”进行比较。 Instead you are getting a new scope containing a new "var2" that is bound to the value of "var1".相反,您将获得一个包含绑定到“var1”值的新“var2”的新作用域。

The reason for the error message is that as far as the compiler is concerned there is no difference between "var2 ->..." and "_ ->...".错误消息的原因是,就编译器而言,“var2 ->...”和“_ ->...”之间没有区别。 Both match all possible values of "var1".两者都匹配“var1”的所有可能值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM