и возвращает функцию типа
>Int -> (Int –> Int)
. Аналогичным образом эта новая функция принимает параметр типа
>Int
и возвращает функцию типа
>Int -> Int
. Наконец, функция принимает параметр типа
>Int
и возвращает значение того же типа
>Int
.
Рассмотрим пример создания новой функции путём вызова функции с недостаточным числом параметров:
>ghci> let multTwoWithNine = multThree 9
>ghci> multTwoWithNine 2 3
>54
В этом примере выражение >multThree 9
возвращает функцию, принимающую два параметра. Мы называем эту функцию >multTwoWithNine
. Если при её вызове предоставить оба необходимых параметра, то она перемножит их между собой, а затем умножит произведение на >9
.
Вызывая функции не со всеми параметрами, мы создаём новые функции «на лету». Допустим, нужно создать функцию, которая принимает число и сравнивает его с константой >100
. Можно сделать это так:
>compareWithHundred :: Int -> Ordering
>compareWithHundred x = compare 100 x
Если мы вызовем функцию с >99
, она вернёт значение >GT
. Довольно просто. Обратите внимание, что параметр >x
находится с правой стороны в обеих частях определения. Теперь подумаем, что вернёт выражение >compare 100
. Этот вызов вернёт функцию, которая принимает параметр и сравнивает его с константой >100
. Ага-а! Не этого ли мы хотели? Можно переписать функцию следующим образом:
>compareWithHundred :: Int -> Ordering
>compareWithHundred = compare 100
Объявление типа не изменилось, так как выражение >compare 100
возвращает функцию. Функция >compare
имеет тип >(Ord a) => a –> (a –> Ordering)
. Когда мы применим её к 100, то получим функцию, принимающую целое число и возвращающую значение типа >Ordering
.
Инфиксные функции могут быть частично применены при помощи так называемых сечений. Для построения сечения инфиксной функции достаточно поместить её в круглые скобки и предоставить параметр только с одной стороны. Это создаст функцию, которая принимает один параметр и применяет его к стороне с пропущенным операндом. Вот донельзя простой пример:
>divideByTen :: (Floating a) => a –> a
>divideByTen = (/10)
Вызов, скажем, >divideByTen 200
эквивалентен вызову >200 / 10
, равно как и >(/10) 200
:
>ghci> divideByTen 200
>20.0
>ghci> 200 / 10
>20.0
>ghci> (/10) 200
>20.0
А вот функция, которая проверяет, находится ли переданный символ в верхнем регистре:
>isUpperAlphanum :: Char –> Bool
>isUpperAlphanum = (`elem` ['А'..'Я'])
Единственная особенность при использовании сечений – применение знака «минус». По определению сечений, >(–4)
– это функция, которая вычитает четыре из переданного числа. В то же время для удобства (–4) означает «минус четыре». Если вы хотите создать функцию, которая вычитает четыре из своего аргумента, выполняйте частичное применение таким образом: