Изучай Haskell во имя добра! (Липовача) - страница 47

и возвращает функцию типа >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) означает «минус четыре». Если вы хотите создать функцию, которая вычитает четыре из своего аргумента, выполняйте частичное применение таким образом: