Haskell Language
Синтаксис вызова функции
Поиск…
Вступление
Синтаксис вызова функции Haskell, объясненный с помощью сравнений с языками языка C, где это применимо. Это направлено на людей, которые приезжают в Haskell с фона на языках C-стиля.
замечания
В общем случае правило для преобразования вызова функции C-стиля в Haskell в любом контексте (назначение, возврат или встроенный в другой вызов) заключается в замене запятых в списке аргументов стиля C пробелом и перемещении открытия скобки из вызова стиля С, чтобы содержать имя функции и ее параметры.
Если какие-либо выражения полностью заключены в круглые скобки, эти (внешние) пары круглых скобок могут быть удалены для удобочитаемости, поскольку они не влияют на значение выражения.
Существуют и другие обстоятельства, при которых скобки могут быть удалены, но это влияет только на читаемость и удобство обслуживания.
Скобки в вызове базовой функции
Для вызова функции стиля C, например
plus(a, b); // Parentheses surrounding only the arguments, comma separated
Тогда эквивалентный код Haskell будет
(plus a b) -- Parentheses surrounding the function and the arguments, no commas
В Haskell круглые скобки явно не требуются для приложения-приложения и используются только для устранения неоднозначности выражений, например, в математике; поэтому в тех случаях, когда скобки окружают весь текст в выражении, скобки на самом деле не нужны, и следующее также эквивалентно:
plus a b -- no parentheses are needed here!
Важно помнить, что в языках C-стиля функция
Круглые скобки во встроенных вызовах функций
В предыдущем примере мы не нуждались в круглых скобках, потому что они не влияли на смысл выражения. Однако они часто необходимы в более сложном выражении, как показано ниже.
В C:
plus(a, take(b, c));
В Haskell это становится:
(plus a (take b c))
-- or equivalently, omitting the outermost parentheses
plus a (take b c)
Обратите внимание, что это не эквивалентно:
plus a take b c -- Not what we want!
Можно подумать, что, поскольку компилятор знает, что функция take
является функцией, она сможет узнать, что вы хотите применить ее к аргументам b
и c
и передать ее результат в plus
.
Однако в Haskell функции часто принимают другие функции в качестве аргументов, и между фактическими различиями между функциями и другими значениями мало фактического различия; и поэтому компилятор не может принять ваше намерение просто потому, что take
- это функция.
Итак, последний пример аналогичен следующему вызову функции C:
plus(a, take, b, c); // Not what we want!
Частичное применение - часть 1
В Haskell функции могут быть частично применены; мы можем рассматривать все функции как принимающие один аргумент и возвращающие измененную функцию, для которой этот аргумент является постоянным. Чтобы проиллюстрировать это, мы можем скопировать функции следующим образом:
(((plus) 1) 2)
Здесь функция (plus)
применяется к 1
давая функцию ((plus) 1)
, которая применяется к 2
, что дает функцию (((plus) 1) 2)
. Поскольку plus 1 2
- это функция, которая не принимает аргументов, вы можете считать ее простой; однако в Haskell существует небольшое различие между функциями и значениями.
Чтобы подробнее остановиться, функция plus
- это функция, которая добавляет свои аргументы.
Функция plus 1
- это функция, которая добавляет 1
к ее аргументу.
Функция plus 1 2
- это функция, которая добавляет 1
к 2
, что всегда является значением 3
.
Частичное применение - часть 2
В качестве другого примера у нас есть map
функций, которая принимает функцию и список значений и применяет функцию к каждому значению списка:
map :: (a -> b) -> [a] -> [b]
Предположим, мы хотим увеличить каждое значение в списке. Вы можете определить свою собственную функцию, которая добавляет ее в свой аргумент и map
эту функцию над вашим списком.
addOne x = plus 1 x
map addOne [1,2,3]
но если у вас есть другой взгляд на определение addOne
, с добавлением круглых скобок для акцента:
(addOne) x = ((plus) 1) x
Функция addOne
, применяемая к любому значению x
, такая же, как частично примененная функция plus 1
примененная к x
. Это означает, что функции addOne
и plus 1
идентичны, и мы можем избежать определения новой функции, просто заменив addOne
на plus 1
, не забывая использовать круглые скобки для выделения plus 1
в качестве подвыражения:
map (plus 1) [1,2,3]