Учебник по 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

Книга посвящена возможностям самого популярного средства цифрового видеомонтажа – Adobe Premiere 6.5. Описываются основные приемы работы с программой, приводятся сведения об управлении проектами и клипами, обсуждаются методы монтажа видео и звука, техника создания титров и добавления спецэффектов, а также освещается процесс окончательного монтирования фильма. На примерах рассматриваются все этапы создания и обработки фильмов для телевидения, видео и мультимедиа.Для широкого круга пользователей.


Финансовое право

В учебном пособии в краткой и доступной форме рассмотрены все основные вопросы, предусмотренные государственным образовательным стандартом и учебной программой по дисциплине «Финансовое право».Книга позволит быстро получить основные знания по предмету, а также качественно подготовиться к зачету и экзамену.Рекомендуется студентам, аспирантам и преподавателям по юридическим, экономическим и управленческим специальностям, а также сотрудникам банков.Автор книги, Шевчук Денис Александрович, имеет опыт преподавания различных дисциплин в ведущих ВУЗах Москвы (экономические, юридические, технические, гуманитарные), два высших образования (экономическое и юридическое), более 30 публикаций (статьи и книги), Член Союза Юристов Москвы, Член Союза Журналистов России, Член Союза Журналистов Москвы, Стипендиат Правительства РФ, опыт работы в банках, коммерческих и государственных структурах (в т.ч.


фгос  ответы

Содержащиеся в пособии контрольно-измерительные материалы (КИМы) для 5 класса, аналогичные материалам ЕГЭ, составлены в соответствии с программой общеобразовательных учреждений по русскому языку и учитывают возрастные особенности учащихся. В конце пособия даны ответы на все варианты тестов, предложены диктанты различных типов.Пособие адресовано учителям, ученикам, их родителям и всем, кому необходимо закрепить и систематизировать знания перед ЕГЭ.


Теория литературы. Чтение как творчество

Цель предлагаемого пособия – систематизировать и обогатить представления о природе, структуре и особенностях художественной литературы как вида искусства, помочь совершенствованию читательского мастерства. Книга снабжена кратким словарем основных литературоведческих понятий и терминов (составлен при участии доцента О.В. Быстровой).Для студентов филологических факультетов, учителей, преподавателей литературы высших и средних учебных заведений.