Учебник по Haskell - [25]
аргументов, сколько у него было дочерних узлов (или подтипов). Так мы строили константы. Но в Haskell мы
можем с помощью применения строить функции на лету, передавая меньшее число аргументов, этот процесс
называется частичным применением или каррированием (currying). Поясним на примере, предположим у нас
есть функция двух аргументов:
add :: Nat -> Nat -> Nat
add a b = ...
На самом деле компилятор воспринимает эту запись так:
add :: Nat -> (Nat -> Nat)
add a b = ...
Функция add является функцией одного аргумента, которая в свою очередь возвращает функцию одного
аргумента (Nat -> Nat). Когда мы пишем в где-нибудь в правой части функции:
... =
... (add Zero (Succ Zero)) ...
Компилятор воспринимает эту запись так:
... =
... ((add Zero) (Succ Zero)) ...
Присмотримся к этому выражению, что изменилось? У нас появились новые скобки, вокруг выражения
(add Zero). Давайте посмотрим как происходит применение:
add :: Nat -> (Nat -> Nat),
Zero :: Nat
----------------------------------------------
(add Zero) :: Nat -> Nat
Итак применение функции add к Zero возвращает новую функцию (add Zero), которая зависит от одного
аргумента. Теперь применим к этой функции второе значение:
(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 и прибавляет к нему двойку. Мы видим, что этой функцией можно
пользоваться также как и обычной функцией.
Попробуем выполнить тоже самое для функции с символьной записью имени:
*Nat> let add2 = (+) (Succ (Succ Zero))
*Nat> add2 Zero
Succ (Succ Zero)
Мы рассмотрели частичное применение для функций в префиксной форме записи. В префиксной фор-
ме записи функция пишется первой, затем следуют аргументы. Для функций в инфиксной форме записи
существует два правила применения.
Это применение слева:
(*) :: a -> (b -> c),
x :: a
-----------------------------
(x *) :: b -> c
И применение справа:
(*) :: a -> (b -> c),
x :: b
-----------------------------
(* x) :: a -> c
Обратите внимание на типы аргумента и возвращаемого значения. Скобки в выражениях (x*) и (*x)
обязательны. Применением слева мы фиксируем в бинарной операции первый аргумент, а применением
справа – второй.
Поясним на примере, для этого давайте возьмём функцию минус (-). Если мы напишем (2-) 1 то мы
получим 1, а если мы напишем (-2) 1, то мы получим -1. Проверим в интерпретаторе:
*Nat> (2-) 1
1
*Nat> (-2) 1
< interactive>:4:2:
Структура функций | 47
No instance for (Num (a0 -> t0))
arising from a use of syntactic negation
Possible fix: add an instance declaration for (Num (a0 -> t0))
In the expression: - 2
In the expression: (- 2) 1
In an equation for ‘it’: it = (- 2) 1
Ох уж этот минус. Незадача. Ошибка произошла из-за того, что минус является хамелеоном. Если мы
пишем -2, компилятор воспринимает минус как унарную операцию, и думает, что мы написали константу
минус два. Это сделано для удобства, но иногда это мешает. Это единственное такое исключение в Haskell.
В книге кратко изложены ответы на основные вопросы темы «Уголовное право. Особенная часть». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.
В книге кратко изложены ответы на основные вопросы темы «Уголовно-исполнительное право». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.
Книга посвящена возможностям самого популярного средства цифрового видеомонтажа – Adobe Premiere 6.5. Описываются основные приемы работы с программой, приводятся сведения об управлении проектами и клипами, обсуждаются методы монтажа видео и звука, техника создания титров и добавления спецэффектов, а также освещается процесс окончательного монтирования фильма. На примерах рассматриваются все этапы создания и обработки фильмов для телевидения, видео и мультимедиа.Для широкого круга пользователей.
В учебном пособии в краткой и доступной форме рассмотрены все основные вопросы, предусмотренные государственным образовательным стандартом и учебной программой по дисциплине «Финансовое право».Книга позволит быстро получить основные знания по предмету, а также качественно подготовиться к зачету и экзамену.Рекомендуется студентам, аспирантам и преподавателям по юридическим, экономическим и управленческим специальностям, а также сотрудникам банков.Автор книги, Шевчук Денис Александрович, имеет опыт преподавания различных дисциплин в ведущих ВУЗах Москвы (экономические, юридические, технические, гуманитарные), два высших образования (экономическое и юридическое), более 30 публикаций (статьи и книги), Член Союза Юристов Москвы, Член Союза Журналистов России, Член Союза Журналистов Москвы, Стипендиат Правительства РФ, опыт работы в банках, коммерческих и государственных структурах (в т.ч.
Содержащиеся в пособии контрольно-измерительные материалы (КИМы) для 5 класса, аналогичные материалам ЕГЭ, составлены в соответствии с программой общеобразовательных учреждений по русскому языку и учитывают возрастные особенности учащихся. В конце пособия даны ответы на все варианты тестов, предложены диктанты различных типов.Пособие адресовано учителям, ученикам, их родителям и всем, кому необходимо закрепить и систематизировать знания перед ЕГЭ.
Цель предлагаемого пособия – систематизировать и обогатить представления о природе, структуре и особенностях художественной литературы как вида искусства, помочь совершенствованию читательского мастерства. Книга снабжена кратким словарем основных литературоведческих понятий и терминов (составлен при участии доцента О.В. Быстровой).Для студентов филологических факультетов, учителей, преподавателей литературы высших и средних учебных заведений.