Spec-Zone.ru › Haskell 9

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)
Алгебраические свойства
Развернуть
  • (*) `on` id = (*) -- (if (*) ∉ {⊥, const ⊥})
  • ((*) `on` f) `on` g = (*) `on` (f . g)
  • flip on f . flip on g = flip on (g . f)

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"]
Алгебраические свойства
Развернуть
  • applyWhen True = id
  • applyWhen False f = id

Начиная с: 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API