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