Поиск…


замечания

Давайте проясним некоторые заблуждения, которые могут сделать новички.

Возможно, вы столкнулись с такими функциями, как:

max :: (Ord a) => a -> a -> a  
max m n  
  | m >= n = m  
  | otherwise = n  

Начинающие обычно рассматривают max :: (Ord a) => a -> a -> a as, которая принимает два аргумента (значения) типа a и возвращает значение типа a . Однако то, что действительно происходит, заключается в том, что max принимает один аргумент типа a и возвращает функцию типа a -> a . Затем эта функция принимает аргумент типа a и возвращает окончательное значение типа a .

Действительно, max можно записать как max :: (Ord a) => a -> (a -> a)

Рассмотрим сигнатуру типа max :

Prelude> :t max  
max :: Ord a => a -> a -> a  

Prelude> :t (max 75)  
(max 75) :: (Num a, Ord a) => a -> a  

Prelude> :t (max "Fury Road")  
(max "Fury Road") :: [Char] -> [Char]  

Prelude> :t (max "Fury Road" "Furiosa")  
(max "Fury Road" "Furiosa") :: [Char]  

max 75 и max "Fury Road" могут не выглядеть как функции, но на самом деле они есть.

Путаница проистекает из того факта, что в математике и многих других обычных языках программирования нам разрешено иметь функции, которые принимают несколько аргументов. Однако в Haskell функции могут принимать только один аргумент, и они могут возвращать либо значения, такие как a , либо такие функции, как a -> a .

Частично примененная функция добавления

Мы можем использовать частичное приложение для «блокировки» первого аргумента. После применения одного аргумента мы остаемся с функцией, которая ожидает еще один аргумент перед возвратом результата.

(+) :: Int -> Int -> Int

addOne :: Int -> Int
addOne = (+) 1

Затем мы можем использовать addOne , чтобы добавить его в Int .

> addOne 5
6
> map addOne [1,2,3]
[2,3,4]

Возврат частично прикладной функции

Возвращение частично применяемых функций - это один из способов записи сжатого кода.

add :: Int -> Int -> Int
add x = (+x)

add 5 2

В этом примере (+ x) - частично применяемая функция. Обратите внимание, что второй параметр функции добавления необязательно указывать в определении функции.

Результатом вызова add 5 2 составляет семь.

Разделы

Разделение является кратким способом частичного применения аргументов к инфиксным операторам.

Например, если мы хотим написать функцию, которая добавляет «ing» в конец слова, мы можем использовать раздел, чтобы кратко определить функцию.

> (++ "ing") "laugh"
"laughing"

Обратите внимание, как мы частично применили второй аргумент. Обычно мы можем лишь частично применять аргументы в указанном порядке.

Мы также можем использовать левую секцию для частичного применения первого аргумента.

> ("re" ++) "do"
"redo"

Мы могли бы эквивалентно написать это, используя обычное префиксное частное приложение:

> ((++) "re") "do"
"redo"

Примечание по вычитанию

Начинающие часто неправильно разделяют отрицание.

> map (-1) [1,2,3]
***error: Could not deduce...

Это не работает, поскольку -1 анализируется как литерал -1 а не секционированный оператор - применяется к 1 . Функция subtract существует, чтобы обойти эту проблему.

> map (subtract 1) [1,2,3]
[0,1,2]


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow