Если мы говорим о «сумме двух функций» в математическом смысле, то у нас должна быть функция, которая принимает два параметра g
и h
, которые оба являются функциями, и возвращает результат, который также являетсяфункция (обычно обозначается g+h
, и которая такова, что (g+h)(x) = g(x) + h(x)
).
Итак, цель состоит в том, чтобы написать функцию sum
, например:
let sum g h =
...
, котораявозвращает функцию, которая принимает аргумент x
и возвращает f(x) + g(x)
.
Можно сделать это следующим образом:
let sum g h =
fun x -> (g x) + (h x)
Вы можете проверить тип sum
:
val sum : ('a -> int) -> ('a -> int) -> 'a -> int = <fun>
, что означает:
принимает первый аргумент типа ('a -> int)
(который является функцией, которая принимает один аргумент и возвращает целое число: то, которое мы вызвалиg),
он принимает второй аргумент также типа ('a -> int)
(тот, который мы назвали h),
это около функциитакже типа 'a -> int
, что нам и нужно (поскольку g+h
действительно является функцией, которая принимает аргумент и возвращает целое число.
В большинстве языков программирования вы будете вынуждены иметь такое определение функции.В OCaml, благодаря curry и некоторой черной магии, вы можете сказать: «Но подождите, вы решили сгруппировать последние 'a -> int
и назвать этот тип возврата sum
, но не могли бы вывместо этого может быть, что 'a
является третьим аргументом sum
и что его тип возвращаемого значения просто int
"?И это было бы то же самое, что сказать, что мы можем видеть sum
"functor" как функцию, принимающую g
и h
в качестве аргументов и возвращающую новую функцию, которая при вызове x
вернет g(x)+h(x)
, но мы можем эквивалентно увидеть его как функцию, принимающую три аргумента g
, h
и x
и возвращающую g(x)+h(x)
.Эти два видения эквивалентны в OCaml.Таким образом, мы можем упростить наш код и просто написать:
let sum g h x = (g x) + (h x)
Вы можете проверить, что тип этого типа все еще
val sum : ('a -> int) -> ('a -> int) -> 'a -> int = <fun>
, как и ожидалось.
Оттуда вы можете получать удовольствие от синтаксиса и определять свой собственный оператор суммирования для функций, например ++
, например:
let (++) g h x = (g x) + (h x)
, а затем использовать его после определения g
и h
:
let g = ( ( + ) 5 )
and h = ( ( * ) 2 )
in
(g ++ h) 3
, который вернет (g+h)(3) = g(3) + h(3) = (5+3) + (2*3) = 14
.