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

. Поэтому пример можно переписать:

>sum $ filter (> 10) $ map (*2) [2..10]

Но кроме избавления от скобок оператор >$ означает, что само применение функции может использоваться как и любая другая функция. Таким образом, мы можем, например, применить функцию к списку функций:

>ghci> map ($ 3) [(4+), (10*), ( 2), sqrt]

>[7.0,30.0,9.0,1.7320508075688772]

Функция >($ 3) применяется к каждому элементу списка. Если задуматься о том, что она делает, то окажется, что она берёт функцию и применяет её к числу >3. Поэтому в данном примере каждая функция из списка применится к тройке, что, впрочем, и так очевидно.

Композиция функций


В математике композиция функций определяется следующим образом:

(f>°g)(x) = f (g (x))

Это значит, что композиция двух функций создаёт новую функцию, которая, когда её вызывают, скажем, с параметром x, эквивалентна вызову g с параметром x, а затем вызову f с результатом первого вызова в качестве своего параметра.

В языке Haskell композиция функций понимается точно так же. Мы создаём её при помощи оператора >(.), который определён следующим образом:

>(.) :: (b –> c) –> (a –> b) –> a –> c

>f . g = \x –> f (g x)

По декларации типа функция >f должна принимать параметр того же типа, что и результат функции >g. Таким образом, результирующая функция принимает параметр того же типа, что и функция >g, и возвращает значение того же типа, что и функция >f. Выражение >negate . (* 3) возвращает функцию, которая принимает число, умножает его на три и меняет его знак на противоположный.

Одно из применений композиции функций – это создание функций «на лету» для передачи их другим функциям в качестве параметров. Конечно, мы можем использовать для этого анонимные функции, но зачастую композиция функций понятнее и лаконичнее. Допустим, что у нас есть список чисел и мы хотим сделать их отрицательными. Один из способов сделать это – получить абсолютное значение числа (модуль), а затем перевести его в отрицательное, вот так:

>ghci> map (\x –> negate (abs x)) [5,–3,–6,7,–3,2,–19,24]

>[–5,–3,–6,–7,–3,–2,–19,–24]

Обратите внимание на анонимную функцию и на то, как она похожа на результирующую композицию функций. А вот что выйдет, если мы воспользуемся композицией:

>ghci> map (negate . abs) [5,–3,–6,7,–3,2,–19,24]

>[–5,–3,–6,–7,–3,–2,–19,–24]

Невероятно! Композиция функций правоассоциативна, поэтому у нас есть возможность включать в неё много функций за один раз. Выражение >f (g (z x)) эквивалентно >(f . g . z) x. Учитывая это, мы можем превратить

>ghci> map (\xs –> negate (sum (tail xs))) [[1..5],[3..6],[1..7]]