Адам уже ответил на это, но я хочу научить вас ловить рыбу.
Каждый раз, когда вы вводите функцию в интерпретатор SML, вы получите ответ с сигнатурой типа функции. Вот первый один:
- fun mymap f xs = List.foldr (fn (x, l) => (f x)::l) [] xs;
val mymap = fn : ('a -> 'b) -> 'a list -> 'b list
А вот второй один:
- fun mymap f = (fn xs => List.foldr (fn (x, l) => (f x)::l) [] xs);
val mymap = fn : ('a -> 'b) -> 'a list -> 'b list
Первое, что мы замечаем, они имеют ту же сигнатуру, что согласуется с утверждением о том, что второй является Обессахаренный формы первого.
Согласно подписи, mymap
принимает функцию, которая отображает один тип в другой. Давайте экспериментировать, используя Int.toString
:
- mymap Int.toString;
val it = fn : int list -> string list
Мы только что сделали частичное применение функции mymap
, что возможно только потому, что mymap
является кэрри функцию.
Для сравнения, давайте посмотрим, что произойдет с версией mymap
, которая не является точной.
- fun mymapUncurried (f,xs) = List.foldr (fn (x, l) => (f x)::l) [] xs;
val mymapUncurried = fn : ('a -> 'b) * 'a list -> 'b list
Это то же, что и ваша первая функция, за исключением того, что аргументы заключены в кортеж. В результате сигнатура типа также отличается (см. *
?). mymapUncurried
принимает 2-кортеж, первый элемент которого имеет тип ('a -> 'b)
и второй аргумент которого имеет тип 'a list
. Теперь частичное приложение не работает:
- mymapUncurried Int.toString;
stdIn:9.1-9.28 Error: operator and operand don't agree [tycon mismatch]
operator domain: ('Z -> 'Y) * 'Z list
operand: int -> string
in expression:
mymapUncurried Int.toString
Однако полное приложение действительно работает. Просто не забудьте передать аргументы в виде кортежа:
- mymapUncurried (Int.toString, [1,2,3]);
val it = ["1","2","3"] : string list
Да, это действительно так же, как и предыдущее (после обессеривания) –