这可能是最简单的一个例子。
假设我有一个相当冗长的函数,它将 x 整数提升为 nth 幂。
let powInt = function
| x,n ->
let rec loop acc n =
match n with
| 0 -> acc
| v -> loop (acc * x) (v-1)
loop 1 n
如果我现在想将整数列表中的每个整数提升到 nth 幂,我认为 F#中的酷List.map
函数将是要走的路:
let powIntList (xs: int list) = List.map powInt xs
但是,在最后一个片段中, n 的力量缺乏映射中的参数 - 而int x
由函数map
隐式提取。
我们如何在此示例中添加 n power参数?
答案 0 :(得分:6)
你让你的功能成为现实。
这正是 currying 的情况,这是一种以这样一种方式制定你的功能的技术,即它们可以“逐个”地获取参数。在数学上,这样的函数只接受一个参数,并返回另一个接受第二个参数的函数。像这样:
let curriedPowInt = fun n -> fun x -> powInt (x, n)
这种定义功能的方式很常见。事实上,对于ML语言(其中F#是一种语言)的本质而言,它有一个特殊的语法:
let curriedPowInt n x = powInt (x, n)
看看我如何在一行中列出我的参数,用n x =
之类的空格分隔它们?这是fun n -> fun x ->
的语法糖。从逻辑上讲,它定义了一个“逐个”引用参数的函数,而不是一次作为元组。
既然你有这样的功能,你可以部分应用 - 也就是说,只给它一个参数,而不是两个:
let pow2 = curriedPowInt 2
这是有效的,因为 - 记得吗? - 我的函数curriedPowInt
接受n
并返回另一个x
的函数。 pow2
的类型现在为int -> int
。这是一个函数,需要int
并将其提升到第二个幂。
当然,你也可以使用内联技巧:
let powIntList (xs: int list) = List.map (curriedPowInt n) xs
另外,请注意我如何更改参数的顺序。我将n
参数放在第一位,将x
参数放在最后。这是使您的函数更有用的一般规则:将“最重要”参数放在最后,将“最不重要”放在第一位。例如,查看List.map
本身:它所操作的列表是两者的最后一个参数。
最后,我建议不要声明powInt
,而是单独声明curriedPowInt
,而不是声明let powInt n x =
let rec loop acc n =
match n with
| 0 -> acc
| v -> loop (acc * x) (v-1)
loop 1 n
let powIntList (xs: int list) = List.map (powInt n) xs
。只需将所有功能都用于咖喱。 Curried函数更有用。事实上,我很少见到未经证实的函数会有用的场合,我可能也从未见过任何函数。
所以,总结一下:
<meta http-equiv="refresh" content="0;URL='http://yourdomain.com/mainsite/'" />