Математическая нотация вызова функции традиционно полагала заключение параметров вызова в скобки. Эту традицию впоследствии переняли практически все императивные языки. Однако в функциональных языках принята иная нотация — имя функции отделяется от её параметров просто пробелом. В Lisp’е вызов функции length с неким параметром L записывается в виде списка: (length L). Такая нотация объясняется тем, что большинство функций в функциональных языках каррированны.
В Haskell’е нет нужды обрамлять вызов функции в виде списка. Например, если определена функция, складывающая два числа:
add :: Integer -> Integer -> Integer
add x y = x + y
То ее вызов с конкретными параметрами (например, 5 и 7) будет выглядеть как:
add 5 7
Здесь видно, что нотация Haskell’а наиболее сильно приближена к нотации абстрактного математического языка. Однако Haskell пошел еще дальше Lisp’а в этом вопросе, и в нем есть нотация для описания некаррированных функций, т.е. тип которых нельзя представить в виде A1 ® (A2 ® ... (An ® B) ... ). И эта нотация, как и в императивных языках программирования, использует круглые скобки:
add (x, y) = x + y
Можно видеть, что последняя запись — это функция с одним аргументом в строгой нотации Haskell’а. С другой стороны для каррированных функций вполне возможно делать частичное применение. Т.е. при вызове функции двух аргументов передать ей только один. Как показано в предыдущей лекции результатом такого вызова будет также функция. Более чётко этот процесс можно проиллюстрировать на примере функции inc, которая прибавляет единицу к заданному аргументу:
inc :: Integer -> Integer
inc = add 1
Т.е. в этом случае вызов функции inc с одним параметром просто приведет к вызову функции add с двумя, первый из которых — 1. Это интуитивное понимание понятия частичного применения. Для закрепления понимания можно рассмотреть классический пример — функция map (её определение на абстрактном функциональном языке приведено во второй лекции). Вот определение функции map на Haskell’е:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : (map f xs)
Как видно, здесь использована инфиксная запись операции prefix — двоеточие, только такая запись используется в нотации Haskell’а для обозначения или конструирования пары. После приведенного выше определения можно произвести следующий вызов:
map (add 1) [1, 2, 3, 4]
Результатом этого вызова будет список [2, 3, 4, 5].