这被认为是一个curry功能?

时间:2013-02-24 17:36:49

标签: functional-programming sml currying

我对currying感到有点困惑 -

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

2 个答案:

答案 0 :(得分:4)

是的,两个功能都是咖喱。实际上,第一个函数是第二个函数的简写。

答案 1 :(得分: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是一个curried函数。

相比之下,让我们看一下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