3

我仍然对咖喱有点困惑 -

我在 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);
4

2 回答 2

4

是的,这两个函数都是柯里化的。事实上,第一个函数是第二个函数的简写。

于 2013-02-24T17:40:09.507 回答
2

亚当已经回答了这个问题,但我想教你钓鱼。

每次您在 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
于 2013-02-25T16:26:30.300 回答