52700.fb2
0.6330525927559899
Prelude> f 15
0.7978497904127007
Функция foldr заменит в списке каждый конструктор (:) на функцию композиции, а пустой список на
функцию id. В результате получается композиция из всех функций в списке.
Это очень похоже на сложение или умножение чисел в списке. При этом в качестве нуля (для сложения)
или единицы (для умножения) мы используем функцию id. Мы пользуемся тем, что по определению для
любой функции f выполнены тождества:
f
. id
==
f
id . f
==
f
Поэтому мы можем использовать id в качестве накопителя результата композиции, как в случае:
Prelude> foldr (*) 1 [1,2,3,4]
24
Если сравнить (. ) с умножением, то id похоже на единицу, а (const a) на ноль. В самом деле для любой
функции f и любого значения a выполнено тождество:
const a
.
f
== const a
Мы словно умножаем функцию на ноль, делая её вычисление бессмысленным.
74 | Глава 5: Функции высшего порядка
Функция перестановки
Функция перестановки flip принимает функцию двух аргументов и меняет аргументы местами:
flip
:: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
К примеру:
Prelude> foldr (-) 0 [1,2,3,4]
-2
Prelude> foldr (flip (-)) 0 [1,2,3,4]
-10
Иногда это бывает полезно.
Функция on
Функция on (от англ. на) перед применением бинарной функции пропускает аргументы через унарную
функцию:
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(.*. ) ‘on‘ f = \x y -> f x .*. f y
Она часто используется в сочетании с функцией sortBy из модуля Data.List. Эта функция имеет тип:
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
Она сортирует элементы списка согласно некоторой функции упорядочивания f :: (a -> a -> Ordering).
С помощью функции on мы можем легко составить такую функцию на лету:
let xs = [(3, ”John”), (2, ”Jack”), (34, ”Jim”), (100, ”Jenny”), (-3, ”Josh”)]
Prelude> :m +Data.List Data.Function
Prelude Data.List Data.Function>