Учебник по Haskell | страница 51
аргумента. Теперь применим к этой функции второе значение:
(add Zero) :: Nat -> Nat,
(Succ Zero) :: Nat
----------------------------------------------
((add Zero) (Succ Zero)) :: Nat
И только теперь мы получили константу. Обратите внимание на то, что получившаяся константа не может
принять ещё один аргумент. Поскольку в правиле для применения функция f должна содержать стрелку, а
у нас есть лишь Nat, это значение может участвовать в других выражениях лишь на месте аргумента.
Тоже самое работает и для функций от большего числа аргументов, если мы пишем
fun :: a1 -> a2 -> a3 -> a4 -> res
... = fun a b c d
На самом деле мы пишем
fun :: a1 -> (a2 -> (a3 -> (a4 -> res)))
... = (((fun a) b) c) d
46 | Глава 3: Типы
Это очень удобно. Так, определив лишь одну функцию fun, мы получили в подарок ещё три функции
(fun a), (fun a b) и (fun a b c). С ростом числа аргументов растёт и число подарков. Если смотреть на
функцию fun, как на функцию одного аргумента, то она представляется таким генератором функций типа
a2 -> a3 -> a4 -> res, который зависит от параметра. Применение функций через пробел значительно
упрощает процесс комбинирования функций.
Поэтому в Haskell аргументы функций, которые играют роль параметров или специфических флагов, то
есть аргументы, которые меняются редко обычно пишутся в начале функции. Например
process :: Param1 -> Param2 -> Arg1 -> Arg2 -> Result
Два первых аргумента функции process выступают в роли параметров для генерации функций с типом
Arg1 -> Arg2 -> Result.
Давайте потренируемся с частичным применением в интерпретаторе. Для этого загрузим модуль Nat из
предыдущей главы:
Prelude> :l Nat
[1 of 1] Compiling Nat
( Nat. hs, interpreted )
Ok, modules loaded: Nat.
*Nat> let add = (+) :: Nat -> Nat -> Nat
*Nat> let addTwo = add (Succ (Succ Zero))
*Nat> :t addTwo
addTwo :: Nat -> Nat
*Nat> addTwo (Succ Zero)
Succ (Succ (Succ Zero))
*Nat> addTwo (addTwo Zero)
Succ (Succ (Succ (Succ Zero)))
Сначала мы ввели локальную переменную add, и присвоили ей метод (+) из класса Num для Nat. Нам
пришлось выписать тип функции, поскольку ghci не знает для какого экземпляра мы хотим определить этот
синоним. В данном случае мы подсказали ему, что это Nat. Затем с помощью частичного применения мы
объявили новый синоним addTwo, как мы видим из следующей строки это функция оного аргумента. Она
принимает любое значение типа Nat и прибавляет к нему двойку. Мы видим, что этой функцией можно