F#

时间:2018-04-30 17:52:44

标签: list f# mapping

这可能是最简单的一个例子。

假设我有一个相当冗长的函数,它将 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参数?

1 个答案:

答案 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/'" />