FSharp.Core中`id`函数的用途是什么?

时间:2017-06-14 12:53:20

标签: .net f# identity

来自Operators.id<'T> Function (F#)

  

身份功能。

     

参数:x类型:'T(输入值)

     

返回值:相同的值

     

F#核心库版本,支持:2.0,4.0,便携式

为什么有一个返回其输入的函数?

3 个答案:

答案 0 :(得分:28)

当使用高阶函数(即返回其他函数和/或将其他函数作为参数的函数)时,您总是必须提供某些作为参数,但是没有&#t; t始终是您想要应用的实际数据转换。

例如,函数Seq.collect展平了一系列序列,并采用了一个返回&#34;嵌套&#34;的函数。 &#34;外部&#34;的每个元素的序列序列。例如,这就是你如何获得某种UI控件的所有孙子的列表:

let control = ...
let allGrandChildren = control.Children |> Seq.collect (fun c -> c.Children)

但很多时候,序列的每个元素本身都已经是一个序列 - 例如,你可能有一个列表列表:

let l = [ [1;2]; [3;4]; [5;6] ]

在这种情况下,传递给Seq.collect的参数函数只需要返回参数:

let flattened = [ [1;2]; [3;4]; [5;6] ] |> Seq.collect (fun x -> x)

此表达式fun x -> x是一个只返回其参数的函数,也称为&#34; 身份函数&#34;。

let flattened = [ [1;2]; [3;4]; [5;6] ] |> Seq.collect id

当使用高阶函数(例如上面的Seq.collect)时,它的使用频繁出现,它应该在标准库中占有一席之地。

另一个引人注目的例子是Seq.choose - 一个过滤Option值序列并同时展开它们的函数。例如,这就是你可以将所有字符串解析为数字并丢弃那些无法解析的字符串:

let tryParse s = match System.Int32.TryParse s with | true, x -> Some x | _ -> None
let strings = [ "1"; "2"; "foo"; "42" ]
let numbers = strings |> Seq.choose tryParse  // numbers = [1;2;42]

但是,如果您已经开始提供Option值列表,该怎么办?救援的身份功能!

let toNumbers optionNumbers =
   optionNumbers |> Seq.choose id

答案 1 :(得分:11)

它对某些高阶函数(将函数作为参数的函数)有用,因此您可以将[object HTMLInputElement]作为参数传递,而不是写出lambda id

(fun x -> x)

答案 2 :(得分:0)

使用选项时,它非常有用。

我写了一个小的惯用JSON-Helper,将所有可选字段都表示为Option,如果将字符串传递为null(如果不是'string option'类型),则会引发错误。

现在有一个提供盒装输出值的函数,可以是

  1. 'a->任何类型,但没有选项
  2. 'b->'x选项

为了正确装箱值,我使用

val |> if isOption then fnOptTransform else id

因此,我将应用高阶函数 fnOptTransform ,然后通过调用 id 来避免编码单独的lambda的麻烦(我尝试避免在其中我可以..)。发现它有用。