52700.fb2
= Little
| n < 30
= Enough
| True
= Many
Специальный символ | уже встречался нам в определении типов. Там он играл роль разделителя аль-
тернатив в сумме типов. Здесь же он разделяет альтернативы в условных выражениях. Сначала мы пишем
| затем выражение-предикат, которое возвращает значение типа Bool, затем равно и после равно – возвра-
щаемое значение. Альтернативы так же как и в случае декомпозиции аргументов функции обходятся сверху
вниз, до тех пор пока в одной из альтернатив предикат не вернёт значение True. Обратите внимание на то,
что нам не нужно писать во второй альтернативе:
| 10 <= n && n < 30
= Enough
Если вычислитель дошёл до этой альтернативы, значит значение точно больше либо равно 10. Поскольку
в предыдущей альтернативе предикат вернул False.
Предикат в последней альтернативе является константой True, он пройдёт сопоставление с любым зна-
чением n. В данном случае, если учесть предыдущие альтернативы мы знаем, что если вычислитель дошёл
до последней альтернативы , значение n больше либо равно 30. Для повышения наглядности кода в Prelude
определена специальная константа-синоним значению True под именем otherwise.
Определим функцию filter для списков в более декларативном стиле, для этого заменим if-выражение
в исходной версии на охранные выражения:
filter :: (a -> Bool) -> [a] -> [a]
filter
p
[]
= []
filter
p
(x:xs)
| p x
= x : rest
| otherwise
= rest
where rest = filter p xs
Или мы можем разместить охранные выражения по-другому:
filter :: (a -> Bool) -> [a] -> [a]
filter
p
[]
= []
filter
p
(x:xs)
| p x
= x : rest
| otherwise = rest
where rest = filter p xs
Отметим то, что локальная переменная rest видна и в той и в другой альтернативе. Вы спокойно можете
пользоваться локальными переменными в любой части уравнения, в котором они определены.