【发布时间】:2013-09-18 07:07:49
【问题描述】:
我最近开始学习 F#,并遇到了一些简单示例的 curried 函数,例如:
考虑一个函数,它通过将价格p 乘以售出的单位数量n 来计算销售额。
let sales (p,n) = p * (float n);;
这个函数的类型被给出为
val sales : p:float * n:int -> float
即取一对float 和int 并返回float。
我们可以把它写成柯里化函数
let salesHi p n = p * (float n);;
这个函数的类型被给出为
val salesHi : p:float -> n:int -> float
即接受float 并将int 的函数 返回到float。
在简单的情况下,这似乎没有什么区别
sales (0.99, 100);;
salesHi 0.99 100;;
两个都给
val it : float = 99.0
但是,使用 curried 函数,我可以输入特定项目的价格以获得新功能。例如
let salesBeer = salesHi 5.99;;
let salesWine = salesHi 14.99;;
然后salesBeer 2 给出11.98 和salesWine 2 给出29.98。
另外,我注意到像+ 这样的内置运算符被定义为函数,所以我可以这样写,例如:
let plus2 = (+) 2;
List.map plus2 [1;3;-1];;
得到
val it : int list = [3; 5; 1]
这似乎是一件好事。因此,当我想用命令式语言实现一个函数,该函数将采用 n > 1 参数时,我是否应该总是在 F# 中使用柯里化函数(只要参数是独立的)?或者我应该采取简单的路线并使用带有n-tuple 的常规函数并在必要时稍后使用curry?还是别的什么?
F# 程序员如何决定何时以柯里化形式创建函数或使用带有元组的常规函数?
【问题讨论】:
-
术语 higher-order function 通常是指接受/返回函数的函数,而您的问题似乎与“元组”与“多个参数”有关。你可能想稍微改写一下。也就是说,为了柯里化,我更喜欢多参数函数。
-
@MarcinŁoś 谢谢我添加了一些关于
sales和salesHi类型的内容,以使其更清晰。也有可能我没有在我的问题中使用标准术语。 -
所谓的“高阶”函数实际上是一个curried 函数,而不是一个元组形式的函数。使用函数式语言时,函数通常采用柯里化形式,因为这允许部分应用。
-
@Lee 感谢您的澄清和编辑。在我正在阅读的文本中,像
(+)和sales这样的函数被称为高阶函数,并且柯里化甚至不在索引中(但是它出现在练习中)。我把它放在another question 中,因为我似乎使用了不恰当的术语,但考虑到书中所说的以及这里有经验的 F#ers 所说的话,我不确定什么是正确的。