Изучай Haskell во имя добра! (Липовача) - страница 16

, т. е. >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]