вызовет функцию
>(+3)
с параметром
>3
,
>(+2)
– с параметром
>3
и
>(+1)
– с параметром
>3
и вернёт все эти результаты в виде списка.
Выполнение выражения >(+) <$> (+3) <*> (*2)
создаст функцию, которая принимает параметр, передаёт его и функции >(+3)
и >(*2)
, а затем вызывает оператор >+
с этими двумя результатами. Соответственно, есть смысл в том, что выражение >sequenceA [(+3),(*2)]
создаёт функцию, которая принимает параметр и передаёт его всем функциям в списке. Вместо вызова оператора >+
с результатами функций используется сочетание >:
и >pure []
для накопления этих результатов в список, который является результатом этой функции.
Использование функции >sequenceA
полезно, когда у нас есть список функций и мы хотим передать им всем один и тот же ввод, а затем просмотреть список результатов. Например, у нас есть число и нам интересно, удовлетворяет ли оно всем предикатам в списке. Вот один из способов это сделать:
>ghci> map (\f –> f 7) [(>4),(<10),odd]
>[True,True,True]
>ghci> and $ map (\f –> f 7) [(>4),(<10),odd]
>True
Вспомните, что функция >and
принимает список значений типа >Bool
и возвращает значение >True
, если все они равны >True
. Ещё один способ достичь такого же результата – применение функции >sequenceA
:
>ghci> sequenceA [(>4),(<10),odd] 7
>[True,True,True]
>ghci> and $ sequenceA [(>4),(<10),odd] 7
>True
Выражение >sequenceA
>[(>4),(<10),odd]
создаёт функцию, которая примет число, передаст его всем предикатам в списке >[(>4),(<10),odd]
и вернёт список булевых значений. Она превращает список с типом >(Num a) => [a –> Bool]
в функцию с типом >(Num a) => a –> [Bool]
. Правда, клёво, а?
Поскольку списки однородны, все функции в списке должны быть одного и того же типа, конечно же. Вы не можете получить список вроде >[ord,
>(+3)]
, потому что функция >ord
принимает символ и возвращает число, тогда как функция >(+3)
принимает число и возвращает число.
При использовании со значением >[]
функция >sequenceA
принимает список списков и возвращает список списков. На самом деле она создаёт списки, которые содержат все комбинации находящихся в них элементов. Проиллюстрируем это предыдущим примером, который выполнен с применением функции >sequenceA
, а затем с помощью генератора списков:
>ghci> sequenceA [[1,2,3],[4,5,6]]
>[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
>ghci> [[x,y] | x <– [1,2,3], y <– [4,5,6]]
>[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
>ghci> sequenceA [[1,2],[3,4]]
>[[1,3],[1,4],[2,3],[2,4]]
>ghci> [[x,y] | x <– [1,2], y <– [3,4]]
>[[1,3],[1,4],[2,3],[2,4]]
>ghci> sequenceA [[1,2],[3,4],[5,6]]