traverse :: Applicativef =>(a ->f b) ->t a ->f (t b)
Тип очень похож на тип функции mapM. И не случайно, ведь mapM определяется через sequence. Только
теперь вместо списка стоит более общий тип. Это тип Foldable, который определяет список как нечто,
на чём можно проводить операции свёртки.
250 | Глава 16: Категориальные типы
Глава 17
Дополнительные возможности
В этой главе мы рассмотрим некоторые дополнительные возможности языка и расширения, они часто
используются в серьёзных программах. Можно писать программы и без них, но с ними гораздо легче и увле-
кательней.
17.1 Пуд сахара
В этом разделе мы рассмотрим специальный синтаксический сахар, который позволяет более кратко
записывать операции для некоторых структур.
Сахар для списков
Перечисления
Для класса Enumопределён специальный синтаксис составления последовательностей перечисляемых
значений. Так например мы можем составить список целых чисел от нуля до десяти:
Prelude>[0 ..10]
[0,1,2,3,4,5,6,7,8,9,10]
А так мы можем составить бесконечную последовательность положительных чисел:
Prelude>take 20 $[0 ..]
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
Мы можем составлять последовательности с определённым шагом. Так можно выделить все чётные по-
ложительные числа:
Prelude>take 20 $[0, 2 ..]
[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38]
А так мы можем составить убывающую последовательность чисел:
Prelude>[10, 9 ..0]
[10,9,8,7,6,5,4,3,2,1,0]
Что интересно в списке могут находиться не только числа, а любые значения из класса Enum. Например
определим тип:
data Day
= Monday | Tuesday | Wednesday | Thursday
| Friday | Saturday | Sunday
deriving( Show, Enum)
Теперь мы можем написать:
*Week>[ Friday .. Sunday]
[ Friday, Saturday, Sunday]
*Week>[ Monday ..]
[ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
Также шаг последовательности может быть и дробным:
*Week>[0, 0.5 ..4]
[0.0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0]
| 251
Генераторы списков
Генераторы списков (list comprehensions) объединяют в себе функции преобразования и фильтрации спис-
ков. Они записываются так:
[ f x |x <-list, p x]
В этой записи мы фильтруем список list предикатом p и преобразуем результат функцией f. Например
возведём в квадрат все чётные элементы списка:
Prelude>[x *x |x <-[1 ..10], even x]
[4,16,36,64,100]
Предикатов может быть несколько, так например мы можем оставить лишь положительные чётные числа:
Prelude>[x |x <-[ -10 ..10], even x, x >=0]
[0,2,4,6,8,10]
Также элементы могут браться из нескольких списков, посмотрим на все возможные комбинации букв из
пары слов:
Prelude>[ [x,y] |x <-”Hello”, y <-”World”]
[”HW”,”Ho”,”Hr”,”Hl”,”Hd”,”eW”,”eo”,”er”,”el”,
”ed”,”lW”,”lo”,”lr”,”ll”,”ld”,”lW”,”lo”,”lr”,
”ll”,”ld”,”oW”,”oo”,”or”,”ol”,”od”]
Сахар для монад, do-нотация
Монады используются столь часто, что для них придумали специальный синтаксис, который облегчает
подстановку специальных значений в функции нескольких переменных. Монады позволяют комбинировать
специальные функции вида
a ->m b
Если бы эти функции выглядели как обычные функции:
a ->b
их можно было свободно комбинировать с другими функциями. А так нам постоянно приходится поль-
зоваться методами класса Monad. Очень часто функции с побочными эффектами имеют вид:
a1 ->a2 ->a3 -> ... ->an ->m b
А теперь представьте, что вам нужно подставить специальное значение третьим аргументом такой функ-
ции и затем передать ещё в одну такую же функцию. Для облегчения участи программистов было придумано
специальное окружение do, в котором специальные функции комбинируются так словно они являются обыч-
ными. Для этого используется обратная стрелка. Посмотрим как определяется функция sequence в окруже-
нии do:
sequence ::[m a] ->m [a]
sequence []
=return []
sequence (mx :mxs)
= do
x
<-mx
xs <-sequence mxs
Читать дальше