從Operators.id<'T> Function (F#):FSharp.Core中`id`函數的用途是什麼?
身份函數。
參數:x類型:「T(輸入值)
返回值:相同的值
F#核心庫版本,支持的:2.0,4.0,便攜式
爲什麼有沒有一個函數返回它的輸入?
從Operators.id<'T> Function (F#):FSharp.Core中`id`函數的用途是什麼?
身份函數。
參數:x類型:「T(輸入值)
返回值:相同的值
F#核心庫版本,支持的:2.0,4.0,便攜式
爲什麼有沒有一個函數返回它的輸入?
與高階函數時(即返回其他功能和/或採取其他功能參數的函數),你總是必須提供東西作爲參數,但並不總是實際數據轉換,你想申請。
例如,函數Seq.collect
將一系列序列展平,並接受一個函數,該函數爲「外」序列的每個元素返回「嵌套」序列。例如,這就是你怎麼可能得到某種形式的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)
這EXPRES sion fun x -> x
是剛剛返回其參數的函數,也稱爲「標識函數」。
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
'Seq.choose id'示例是一個很好的例子,但是'Seq.collect id'只是一種不太可讀的說'Seq.concat'的方式。 (也就是說,我很確定我已經寫了'Seq.collect id'多次,它說明了'id'做得好!) –
這對於某些高階函數(函數取函數作爲參數),這樣就可以通過id
作爲參數,而不是寫出來的拉姆達(fun x -> x)
有用。
[[1;2]; [3]] |> List.collect id // [1; 2; 3]
在這種情況下,您可以使用'List.concat',它會更具可讀性:-)。 –
有趣的是還要注意數學背景。有一個'無所作爲'的對象提供了重要的結構。由於零是加法下的數字的同一性,並且一個是乘法下的數字的同一性,所以'id'是組合下的一組函數的標識。在函數式語言中,你經常需要將函數作爲對象進行操作,對它們執行操作等。 –
@matt_t_gregg如果你將它作爲答案發布,我相信你會得到不少讚揚。 –
@FyodorSoikin我很高興你的答案涵蓋了爲什麼需要和使用它的實用性 - 我認爲數學的東西更有趣。 –