, т. е.
>x
последовательно принимает все значения элементов списка. Иногда говорят, что
>x
связывается с каждым элементом списка. Часть генератора, находящаяся левее вертикальной черты
>|
, определяет значения элементов результирующего списка. В нашем примере значения
>x
, извлечённые из списка
>[1..10]
, умножаются на два.
Теперь давайте добавим к этому генератору условие выборки (предикат). Условия идут после задания источника данных и отделяются от него запятой. Предположим, что нам нужны только те элементы, которые, будучи удвоенными, больше либо равны 12.
>ghci> [x*2 | x <– [1..10], x*2 >= 12]
>[12,14,16,18,20]
Это работает. Замечательно! А как насчёт ситуации, когда требуется получить все числа от 50 до 100, остаток от деления на 7 которых равен 3? Легко!
>ghci> [ x | x <– [50..100], x `mod` 7 == 3]
>[52,59,66,73,80,87,94]
И снова получилось!
ПРИМЕЧАНИЕ. Заметим, что прореживание списков с помощью условий выборки также называется фильтрацией.
Мы взяли список чисел и отфильтровали их условиями. Теперь другой пример. Давайте предположим, что нам нужно выражение, которое заменяет каждое нечётное число больше 10 на >БАХ!"
, а каждое нечётное число меньше 10 – на >БУМ!"
. Если число чётное, мы выбрасываем его из нашего списка. Для удобства поместим выражение в функцию, чтобы потом легко использовать его повторно.
>boomBangs xs = [if x < 10 then "БУМ!" else "БАХ!" | x <– xs, odd x]
ПРИМЕЧАНИЕ. Помните, что если вы пытаетесь определить эту функцию в GHCi, то перед её именем нужно написать >let
. Если же вы описываете её в отдельном файле, а потом загружаете его в GHCi, то никакого >let
не требуется.
Последняя часть описания – условие выборки. Функция >odd
возвращает значение >True
для нечётных чисел и >False
– для чётных. Элемент включается в список, только если все условия выборки возвращают значение >True
.
>ghci> boomBangs [7..13]
>["БУМ!","БУМ!","БАХ!","БАХ!"]
Мы можем использовать несколько условий выборки. Если бы по требовалось получить все числа от 10 до 20, кроме 13, 15 и 19, то мы бы написали:
>ghci> [x | x <– [10..20], x /= 13, x /= 15, x /= 19]
>[10,11,12,14,16,17,18,20]
Можно не только написать несколько условий выборки в генераторах списков (элемент должен удовлетворять всем условиям, чтобы быть включённым в результирующий список), но и выбирать элементы из нескольких списков. В таком случае выражения перебирают все комбинации из данных списков и затем объединяют их по производящей функции, которую мы указали:
>ghci> [x+y | x <- [1,2,3], y <- [10,100,1000]]
>[11,101,1001,12,102,1002,13,103,1003]