Переменные сопоставления с образцом в операторе case в Haskell

Если я сравниваю строковый литерал со строковым литералом, используя инструкцию case, я получаю ожидаемое поведение: здесь происходит? Как это поведение имеет смысл?

11
задан Don Stewart 13 August 2010 в 20:03
поделиться

3 ответа

Сопоставление с образцом в Haskell связывает новые переменные. Итак, когда вы пишете:

case x of
    y -> ...

, вы привязываете новую переменную «y» к значению «x». Это банальный «узор». Вы можете более ясно увидеть, как работает привязка, когда задействован конструктор:

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

Теперь a и b связываются с компонентами кортежа. И так далее для деконструкции и привязки других типов данных. Таким образом, чтобы сопоставить строковый литерал, вы должны написать:

case x of
    "def" -> ....
21
ответ дан 3 December 2019 в 00:51
поделиться

Это потому, что " case "не делает то, что вы думаете. Параметр «var2», для которого задано значение «def», не сравнивается с «var1». Вместо этого вы получаете новую область, содержащую новую переменную «var2», привязанную к значению «var1».

Причина сообщения об ошибке в том, что для компилятора нет разницы между «var2 -> ...» и «_ -> ...». Оба соответствуют всем возможным значениям "var1".

8
ответ дан 3 December 2019 в 00:51
поделиться

Почему см. Ответ Дона.Распространенная идиома для того, что вы пытаетесь сделать, такова:

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"
26
ответ дан 3 December 2019 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: