Too*_*one 25 f# functional-programming
我最近开始学习F#并遇到curried函数,用于简单示例,如下所示:
考虑一个通过将价格乘以销售p单位数来计算销售额的函数n.
let sales (p,n) = p * (float n);;
Run Code Online (Sandbox Code Playgroud)
该函数的类型为
val sales : p:float * n:int -> float
Run Code Online (Sandbox Code Playgroud)
即采取对float和int并返回float.
我们可以把它写成一个curried函数
let salesHi p n = p * (float n);;
Run Code Online (Sandbox Code Playgroud)
该函数的类型为
val salesHi : p:float -> n:int -> float
Run Code Online (Sandbox Code Playgroud)
即需要一个float和返回功能的int到float.
在简单的情况下,这似乎没有区别
sales (0.99, 100);;
salesHi 0.99 100;;
Run Code Online (Sandbox Code Playgroud)
两者都给
val it : float = 99.0
Run Code Online (Sandbox Code Playgroud)
然而,通过咖喱功能,我可以为特定项目提供价格以获得新功能.例如
let salesBeer = salesHi 5.99;;
let salesWine = salesHi 14.99;;
Run Code Online (Sandbox Code Playgroud)
然后salesBeer 2给出11.98并salesWine 2给出29.98.
另外,我注意到内置的运算符如+定义为函数,所以我可以编写,例如:
let plus2 = (+) 2;
List.map plus2 [1;3;-1];;
Run Code Online (Sandbox Code Playgroud)
得到
val it : int list = [3; 5; 1]
Run Code Online (Sandbox Code Playgroud)
这似乎是一件好事.因此,当我想在一个可以使用n > 1参数的命令式语言中实现一个函数时,我是否应该总是在F#中使用一个curried函数(只要参数是独立的)?或者我应该采取简单的路线,n并在必要时使用常规功能与-tuple和咖喱?或者是其他东西?
F#程序员如何决定何时以curry形式创建函数或使用带有元组的常规函数?
Tom*_*cek 31
当你在curried和tupled形式之间进行选择时,要考虑的主要问题是你作为参数的元组是否意味着什么.
Tupled形式.例如,float * float可能代表一个范围,然后使用tupled形式是个好主意.
let normalizeRange (lo, hi) = if hi < lo then (hi, lo) else (lo, hi)
let expandRange by (lo, hi) = (lo - by, hi + by)
Run Code Online (Sandbox Code Playgroud)
关于这一点的好处是你可以编写适用于范围的函数.你可以写例如:
randomRange() |> normalizeRange |> expandRange 10
Run Code Online (Sandbox Code Playgroud)
咖喱形式.另一方面,如果所有参数的元组不是具有某些有用含义的独立值,则curried形式是更好的选择.例如,幂函数pown 2.0 10- 两个参数是幂和指数,但你不可能(2.0, 10)在你的程序中的其他地方使用元组.
当你有一个"更重要"的参数时,curried表格也很有用,因为那时你可以使用流水线.例如,List.map必须通过咖喱来允许:
[1 .. 10] |> List.map (fun n -> n + 1)
Run Code Online (Sandbox Code Playgroud)