Data.Function
| Авторские права | Nils Anders Danielsson 2006 Alexander Berntsen 2014 |
|---|---|
| Лицензия | В стиле BSD (см. файл LICENSE в дистрибутиве) |
| Сопровождающий | libraries@haskell.org |
| Стабильность | стабильный |
| Переносимость | переносимый |
| Безопасный Haskell | Safe |
| Язык | Haskell2010 |
Содержание
- Prelude: реэкспорт
- Другие комбинаторы
Описание
Простые комбинаторы, работающие исключительно с функциями.
Prelude: реэкспорт
id :: a -> a Исходный код
Функция тождества.
id x = x
На первый взгляд эта функция может показаться бесполезной, но в контексте функций высшего порядка она может быть очень полезна.
Примеры
>>> length $ filter id [True, True, False, True] 3
>>> Just (Just 3) >>= id Just 3
>>> foldr id 0 [(^3), (*5), (+2)] 1000
const :: a -> b -> a Исходный код
const x y всегда вычисляется в x, игнорируя свой второй аргумент.
const x = \_ -> x
На первый взгляд эта функция может показаться бесполезной, но в контексте функций высшего порядка она может быть очень полезна.
Примеры
>>> const 42 "hello" 42
>>> map (const 42) [0..3] [42,42,42,42]
(.) :: (b -> c) -> (a -> b) -> a -> c infixr 9 Исходный код
Композиция функций справа налево.
(f . g) x = f (g x)
f . id = f = id . f
Примеры
>>> map ((*2) . length) [[], [0, 1, 2], [0]] [0,6,2]
>>> foldr (.) id [(+1), (*3), (^3)] 2 25
>>> let (...) = (.).(.) in ((*2)...(+)) 5 10 30
flip :: (a -> b -> c) -> b -> a -> c Исходный код
flip f принимает первые два аргумента в порядке, обратном порядку аргументов f.
flip f x y = f y x
flip . flip = id
Примеры
>>> flip (++) "hello" "world" "worldhello"
>>> let (.>) = flip (.) in (+1) .> show $ 5 "6"
($) :: (a -> b) -> a -> b infixr 0 Исходный код
($) — это оператор применения функции.
Применение ($) к функции f и аргументу x дает тот же результат, что и непосредственное применение f к x. Определение похоже на следующее:
($) :: (a -> b) -> a -> b ($) f x = f x
Это id, полученное специализацией a -> a от (a -> b) -> (a -> b), что в силу ассоциативности (->) равносильно (a -> b) -> a -> b.
На первый взгляд это может показаться бессмысленным! Но на самом деле это один из самых полезных и важных операторов в Haskell.
Порядок операций для ($) и обычного применения функции сильно различается. Обычное применение функции имеет приоритет 10 — выше, чем у любого оператора, — и левоассоциативно. Поэтому следующие два определения эквивалентны:
expr = min 5 1 + 5 expr = ((min 5) 1) + 5
У ($) приоритет 0 (самый низкий), и он правоассоциативен, поэтому следующие выражения эквивалентны:
expr = min 5 $ 1 + 5 expr = (min 5) (1 + 5)
Примеры
Оператор ($) часто используют, чтобы избежать скобок в сложных выражениях.
Например, вместо вложенных скобок в следующей функции Haskell:
-- | Sum numbers in a string: strSum "100 5 -7" == 98 strSum :: String -> Int strSum s = sum (mapMaybe readMaybe (words s))
можно использовать оператор применения функции:
-- | Sum numbers in a string: strSum "100 5 -7" == 98 strSum :: String -> Int strSum s = sum $ mapMaybe readMaybe $ words s
($) также используется как секция (частично примененный оператор), чтобы показать, что мы хотим применить некоторую пока не указанную функцию к заданному значению. Например, чтобы применить аргумент 5 к списку функций:
applyFive :: [Int] applyFive = map ($ 5) [(+1), (2^)] >>> [6, 32]
Техническое замечание (полиморфизм представления)
($) полностью полиморфен относительно представления. Это позволяет использовать его также с аргументами неприводимых и даже неупакованных видов, например с неупакованными целыми числами:
fastMod :: Int -> Int -> Int fastMod (I# x) (I# m) = I# $ remInt# x m
Другие комбинаторы
(&) :: a -> (a -> b) -> b infixl 1 Исходный код
& — это оператор обратного применения. Он обеспечивает удобство записи. Его приоритет на единицу выше приоритета оператора прямого применения $, поэтому & можно вкладывать в $.
Это вариант flip id, где id специализирован от a -> a до (a -> b) -> (a -> b), что в силу ассоциативности (->) равно (a -> b) -> a -> b. Инвертируя его, получаем a -> (a -> b) -> b, что соответствует сигнатуре типа &
Примеры
>>> 5 & (+1) & show "6"
>>> sqrt $ [1 / n^2 | n <- [1..1000]] & sum & (*6) 3.1406380562059946
Начиная с: base-4.8.0.0
fix :: (a -> a) -> a Исходный код
fix f — наименьшая неподвижная точка функции f, то есть наименее определенное x, такое что f x = x.
Когда f является строгой, это означает, что, по определению строгости, f ⊥ = ⊥ и поэтому наименее определенная неподвижная точка любой строгой функции — это ⊥.
Примеры
Функцию факториала можно записать с помощью прямой рекурсии:
>>> let fac n = if n <= 1 then 1 else n * fac (n-1) in fac 5 120
Здесь используется тот факт, что let в Haskell вводит рекурсивные связывания. Это определение можно переписать с помощью fix:
Вместо рекурсивного вызова мы вводим фиктивный параметр rec; при использовании внутри fix этот параметр ссылается на аргумент fix, тем самым возвращая рекурсию.
>>> fix (\rec n -> if n <= 1 then 1 else n * rec (n-1)) 5 120
С помощью fix можно реализовать версии repeat в виде fix . (:) и cycle в виде fix . (++)
>>> take 10 $ fix (0:) [0,0,0,0,0,0,0,0,0,0]
>>> map (fix (\rec n -> if n < 2 then n else rec (n - 1) + rec (n - 2))) [1..10] [1,1,2,3,5,8,13,21,34,55]
Подробности реализации
В текущей реализации fix используется структурное разделение данных
fix f = let x = f x in x
Более простой вариант без разделения выглядел бы так:
fix f = f (fix f)
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c infixl 0 Исходный код
on b u x y применяет бинарную функцию b к результатам применения унарной функции u к двум аргументам x и y. Иными словами, она преобразует два входных значения и объединяет результаты.
(op `on` f) x y = f x `op` f y
Примеры
>>> sortBy (compare `on` length) [[0, 1, 2], [0, 1], [], [0]] [[],[0],[0,1],[0,1,2]]
>>> ((+) `on` length) [1, 2, 3] [-1] 4
>>> ((,) `on` (*2)) 2 3 (4,6)
Алгебраические свойства
applyWhen :: Bool -> (a -> a) -> a -> a Исходный код
applyWhen применяет функцию к значению, если условие истинно; в противном случае возвращает значение без изменений.
Примеры
>>> map (\x -> applyWhen (odd x) (*2) x) [1..10] [2,2,6,4,10,6,14,8,18,10]
>>> map (\x -> applyWhen (length x > 6) ((++ "...") . take 3) x) ["Hi!", "This is amazing", "Hope you're doing well today!", ":D"] ["Hi!","Thi...","Hop...",":D"]
Алгебраические свойства
Начиная с: base-4.18.0.0
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/9.14.1/docs/libraries/base-4.22.0.0-66f8/Data-Function.html