我对问题的理解来自Heilperin's et al. "Concrete Abstraction"。我得到的结论是对函数的求值的转换,该函数将几个参数用于评估函数序列,每个函数都有一个参数。我已经清楚了两种方法之间的语义差异(我可以这样称呼它们吗?)但我确信我没有掌握这两种方法背后的实际意义。
请考虑,在Ocaml:
# let foo x y = x * y;;
foo : int -> int -> int = <fun>
和
# let foo2 (x, y) = x * y;;
foo2 : int * int -> int = <fun>
两个功能的结果相同。 但是,实际上,这两个功能有什么不同呢?可读性?计算效率?我缺乏经验,没有给这个问题足够的阅读。
答案 0 :(得分:3)
首先,我想强调,由于编译器优化,上面的两个函数将被编译成相同的汇编代码。如果没有优化,则currying的成本会过高,即,curried函数的应用需要分配一定数量的闭包,其数量等于参数的数量。
实际上,curried函数对于定义部分应用程序很有用。例如,cf。,
let double = foo 2
let double2 x = foo2 (2,x)
另一个含义是,在curry形式中,您不需要为参数分配临时元组,如上例所示,函数double2
每次都会创建一个不必要的元组(2,x)
叫做。
最后,咖喱表格实际上简化了关于函数的推理,就像现在一样,我们只有N
个函数的N
个家族,而不是一元函数。这允许,为了平等地键入函数,例如,类型'a -> 'b
适用于任何函数,例如int -> int
,int -> int -> int
等。如果没有curry,我们将需要添加一个数字参数函数的类型,带来所有负面后果。
答案 1 :(得分:1)
使用第一个实现,您可以定义,例如
let double = foo 2
第二个实现不能部分重用。