×
Traktatov.net » Изучай Haskell во имя добра! » Читать онлайн
Страница 42 из 245 Настройки

. Мы записали, что >g x y = f y x. Если это верно, то верно и следующее: >f y x = g x y. Держите это в уме – мы можем реализовать функцию ещё проще.

>flip' :: (a –> b –> c) –> b –> a –> c

>flip' f y x = f x y

Здесь мы воспользовались тем, что функции каррированы. Когда мы вызываем функцию >flip' f без параметров >y и >x, то получаем функцию, которая принимает два параметра, но переставляет их при вызове. Даже несмотря на то, что такие «перевёрнутые» функции обычно передаются в другие функции, мы можем воспользоваться преимуществами каррирования при создании ФВП, если подумаем наперёд и запишем, каков будет конечный результат при вызове полностью определённых функций.

>ghci> zip [1,2,3,4,5,6] "привет"

>[(1,'п'),(2,'р'),(3,'и'),(4,'в'),(5,'е'),(6,'т')]

>ghci> flip' zip [1,2,3,4,5] "привет"

>[('п',1),('р',2),('и',3),('в',4),('е',5),('т',6)]

>ghci> zipWith div [2,2..] [10,8,6,4,2]

>[0,0,0,0,1]

>ghci> zipWith (flip' div) [2,2..] [10,8,6,4,2]

>[5,4,3,2,1]

Если применить функцию >flip' к >zip, то мы получим функцию, похожую на >zip, за исключением того что элементы первого списка будут оказываться вторыми элементами пар результирующего списка, и наоборот. Функция >flip' div делит свой второй параметр на первый, так что если мы передадим ей числа >2 и >10, то результат будет такой же, что и в случае >div 10 2.

Инструментарий функционального программиста

Как функциональные программисты мы редко будем обрабатывать одно значение. Обычно нам хочется сразу взять набор чисел, букв или значений каких-либо иных типов, а затем преобразовать всё это множество для получения результата. В данном разделе будет рассмотрен ряд полезных функций, которые позволяют нам работать с множествами значений.

Функция map

Функция >map берёт функцию и список и применяет функцию к каждому элементу списка, формируя новый список. Давайте изучим сигнатуру этой функции и посмотрим, как она определена.

>map :: (a –> b) –> [a] –> [b]

>map _ [] = []

>map f (x:xs) = f x : map f xs

Сигнатура функции говорит нам, что функция >map принимает на вход функцию, которая вычисляет значение типа >b по параметру типа >a, список элементов типа >a и возвращает список элементов типа >b. Интересно, что глядя на сигнатуру функции вы уже можете сказать, что она делает. Функция >map – одна из самых универсальных ФВП, и она может использоваться миллионом разных способов. Рассмотрим её в действии:

>ghci> map (+3) [1,5,3,1,6]

>[4,8,6,4,9]

>ghci> map (++ "!") ["БУХ", "БАХ", "ПАФ"]

>["БУХ!","БАХ!","ПАФ!"]

>ghci> map (replicate 3) [3..6]

>[[3,3,3],[4,4,4],[5,5,5],[6,6,6]]

>ghci> map (map (^2)) [[1,2],[3,4,5,6],[7,8]]

>[[1,4],[9,16,25,36],[49,64]]

>ghci> map fst [(1,2),(3,5),(6,3),(2,6),(2,5)]

>[1,3,6,2,2]

Возможно, вы заметили, что нечто аналогичное можно сделать с помощью генератора списков. Вызов >map (+3) [1,5,3,1,6] – это то же самое, что и >[x+3 | x <– [1,5,3,1,6]]. Тем не менее использование функции >map обеспечивает более читаемый код в случаях, когда вы просто применяете некоторую функцию к списку. Особенно когда применяются отображения к отображениям (>map – к результатам выполнения функции