Короче
Сопоставления с образцом в общем случае сравнениями не являются, и задействуют более примитивный механизм, недоступный сравнениям, однако и сами могут не все, что доступно сравнениям (например, сравнение с переменной). Но в вашем случае стоит задействовать как раз сравнения.
f x
| x == n = 42
| x == n + 1 = 43
| otherwise = 44
where n = 4
в сочетании с case
f x =
let
n = 4
in
case () of
_ | x == n -> 42
| x == n + 1 -> 43
| otherwise -> 44
или даже так, хоть это и не одно и то же (сравнения тут используются в реализациях min
/max
)
f x = max 42 (min 44 (x + 38))
Длиннее
Сопоставлении производится
- с конструкторами данных, как по отдельности, так и в составе выражения например
Nothing
, Left 5
, ([1], Just (Right 2))
, []
- литералами
1
, 'x'
, "test"
- переменными
x
, y
, somethingElse
.
Пеоеменным удачно сопоставляется любое выражение. так что они служат не для сравнивания с ними, а для связывания части сопоставляемого выражения с именем переменной. Т.е., грубо говоря, значение переменной в этом месте присваивается.
ghci> case 5 of {n -> n + 1}
6
в этом примере для всей правой части n
будет равно 5
Так же и в более сложных выражениях
ghci> case Right 1 of {Left n -> -n; Right n -> n}
1
ghci> case Left 2 of {Left n -> -n; Right n -> n}
-2
Смысл здесь такой: если выражение Left 2
соответствует образцу Left n
, чему при этом будет равно n
? В данном случае двум.
Даже если одноименная переменная уже существует, в правой части сопоставления она будет затенена. Поэтому два примера будут иметь одинаковый результат (а значение 0 переменной n
задействовано не будет)
ghci> let n = 0 in case 5 of {n -> n + 1}
6
ghci> let n = 0 in case 5 of {m -> m + 1}
6
Выражения n + k
в сопоставлении с образцом когда-то были частью языка. Они поддерживаются компилятором и сейчас, но по умолчанию отключены, да и все равно делают не то, чего вам хотелось бы.
ghci> :set -XNPlusKPatterns
ghci> case 5 of {n + 1 -> n}
4
Т.е. в данном случае мы сопоставляем 5
с образцом n + 1
, и тогда n
будет равна четырем, так как если бы имея n = 4
мы прибавили бы к ней 1
, то получили бы 5.