我仍然对咖喱有点困惑 -
我在 SML 中有一个 map 的实现,这被认为是一个 curried 函数吗?
fun mymap f xs = List.foldr (fn (x, l) => (f x)::l) [] xs;
还是我需要更明确地强制执行单个参数传递?
fun mymap f = (fn xs => List.foldr (fn (x, l) => (f x)::l) [] xs);
我仍然对咖喱有点困惑 -
我在 SML 中有一个 map 的实现,这被认为是一个 curried 函数吗?
fun mymap f xs = List.foldr (fn (x, l) => (f x)::l) [] xs;
还是我需要更明确地强制执行单个参数传递?
fun mymap f = (fn xs => List.foldr (fn (x, l) => (f x)::l) [] xs);
是的,这两个函数都是柯里化的。事实上,第一个函数是第二个函数的简写。
亚当已经回答了这个问题,但我想教你钓鱼。
每次您在 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 元组,其第一个元素具有 type ('a -> 'b)
,其第二个参数具有 type '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