Если вы посмотрите на типы, то вы ясно увидите, что делают curry
и uncurry
.
Помните, что можно определить функцию, которая принимает свои аргументы как один большой кортеж или как несколько аргументов (в действительности это становится «цепочкой» функций, каждый из которых принимает 1 аргумент, см. wiki ):
fun foo (a,x) = a*x+10
fun bar a x = a*x+20
Разница отчетливо видна в их типах:
val foo = fn : int * int -> int
val bar = fn : int -> int -> int
Функция curry
"преобразует" функцию, которая принимает свои аргументы в виде кортежа, в "цепочку" функций, каждая из которых принимает 1 из аргументов. Это особенно удобно, когда мы хотим составить ряд функций, некоторые из которых были частично применены с аргументами. Посмотрите, как меняется тип foo
:
- curry foo;
val it = fn : int -> int -> int
Теперь мы можем попытаться скомпоновать две функции:
- (curry foo 5 o bar 1) 4;
val it = 130 : int
Первые 4 применяются к bar 1
в качестве аргумента x
, затем результат этого вычисления (bar 1 4
) дается в качестве x
аргумента для foo
.
Очевидно, uncurry
используется для обратного процесса:
- uncurry bar;
val it = fn : int * int -> int