Соответствующие переменные шаблонов в случае case в Haskell
Если я сравниваю строковый литерал с строковым литералом с использованием оператора 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"
Что здесь происходит? Как это имеет смысл?
Ответы
Ответ 1
См. ответ "Дон" для чего. Обычная идиома для выполнения того, что вы пытаетесь сделать, такова:
var1 = "abc"
var2 = "def"
foo x = case () of
() | x == var1 -> "Fail"
| x == var2 -> "Failzor"
| otherwise -> "WIN"
Конечно, в этом случае мы потеряли бы case
и просто напишем охранники непосредственно на функцию:
foo x | x == var1 = "Fail"
| ...
UPDATE
В наши дни расширение MultiWayIf
делает это со слегка меньшим синтаксическим шумом.
{-# LANGUAGE MultiWayIf #-}
foo x = if | x == var1 -> "Fail"
| x == var2 -> "Failzor"
| otherwise -> "WIN"
Ответ 2
Соответствие шаблону в Haskell связывает новые переменные. Поэтому, когда вы пишете:
case x of
y -> ...
теперь вы привязали новую переменную "y" к значению "x". Это тривиальный "шаблон". Вы можете более четко увидеть, как привязка работает при использовании конструктора:
case x of
(a, b) -> ...
Теперь a и b привязываются к компонентам кортежа. И так далее для деконструкции и привязки других типов данных.
Таким образом, чтобы соответствовать строковому литералу, вы должны написать:
case x of
"def" -> ....
Ответ 3
Это потому, что "случай" не делает то, что вы думаете. "Var2", который был установлен в "def", не сравнивается с "var1" . Вместо этого вы получаете новую область, содержащую новый "var2", который привязан к значению "var1" .
Причиной сообщения об ошибке является то, что в отношении компилятора нет разницы между "var2 → ..." и "_ → ...". Оба соответствуют всем возможным значениям "var1" .