Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of `id` function in the FSharp.Core?

Tags:

.net

identity

f#

From Operators.id<'T> Function (F#):

The identity function.

Parameters: x Type: 'T (The input value)

Return Value: The same value

F# Core Library Versions, supported in: 2.0, 4.0, Portable

Why is there a function that returns its input?

like image 658
MiP Avatar asked Jun 14 '17 12:06

MiP


2 Answers

When working with higher-order functions (i.e. functions that return other functions and/or take other functions as parameters), you always have to provide something as parameter, but there isn't always an actual data transformation that you'd want to apply.

For example, the function Seq.collect flattens a sequence of sequences, and takes a function that returns the "nested" sequence for each element of the "outer" sequence. For example, this is how you might get the list of all grandchildren of a UI control of some sort:

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

But a lot of times, each element of the sequence will already be a sequence by itself - for example, you may have a list of lists:

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

In this case, the parameter function that you pass to Seq.collect needs to just return the argument:

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

This expression fun x -> x is a function that just returns its argument, also known as "identity function".

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

Its usage crops up so often when working with higher-order functions (such as Seq.collect above) that it deserves a place in the standard library.

Another compelling example is Seq.choose - a function that filters a sequence of Option values and unwraps them at the same time. For example, this is how you might parse all strings as numbers and discard those that can't be parsed:

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] 

But what if you're already given a list of Option values to start with? The identity function to the rescue!

let toNumbers optionNumbers =    optionNumbers |> Seq.choose id 
like image 183
Fyodor Soikin Avatar answered Oct 06 '22 00:10

Fyodor Soikin


It's useful for certain higher order functions (functions that take functions as arguments) so that you can pass id as the argument instead of writing out the lambda (fun x -> x).

[[1;2]; [3]] |> List.collect id  // [1; 2; 3] 
like image 33
TheQuickBrownFox Avatar answered Oct 05 '22 22:10

TheQuickBrownFox