Data.Function
| Авторские права | Нильс Андерс Даниэльссон 2006 Александр Бернтсен 2014 |
|---|---|
| Лицензия | BSD-стиль (см. файл LICENSE в дистрибутиве) |
| Поддержка | libraries@haskell.org |
| Устойчивость | стабильная |
| Переносимость | переносимая |
| Safe Haskell | Безопасная |
| Язык | Haskell2010 |
Содержание
- Prelude повторный экспорт
- Другие комбинаторы
Описание
Простые комбинаторы, работающие только с функциями.
Prelude повторный экспорт
Функция тождества.
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 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 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 применяет функцию к значению, если условие истинно, в противном случае возвращает значение без изменений.
Это эквивалентно flip (bool id).
Примеры
>>> 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.12.1/docs/libraries/base-4.21.0.0-8e62/Data-Function.html