F# is a functional language, therefore the LINQ functionality in .NET (which is also functional) comes naturally to F#. In this article we will compare LINQ expressions to the equivalent F# expressions for an F# List and show how to use projection, filtering, and other LINQ goodies in F#.
Projection
Projection is the art of mapping one value into another. In LINQ we generally map an entire collection into a new collection based on the demands of a particular function using the Select method.
Let's say we have a sequence of numbers in C# from 0 to 10:
int[] integers = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
We can easily map each one of these numbers to an even number by multiplying each one by 2. Using LINQ this is a fairly straightforward Select call.
var evens = integers.Select(e => e * 2).ToArray();
The result of this call is:
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
How do we do the same thing in F#? A list is defined in F# as follows:
let integers = [0;1;2;3;4;5;6;7;8;9;10]
You can also write the equivalent list declaration in F# as:
let integers= [0..10]
To do the projection in F#, you write a similar expression that you would in LINQ. The only difference is that you "pipe" your list into the list projection function. Here is the equivalent LINQ expression in F# for generating even numbers:
let evens = integers |> List.map(fun(x) -> x * 2)
The map List function in F# is the same as the LINQ Select in C#. The lambda expression is passed the same way as C# , inside the projection call. fun(x) -> x * 2 is equivalent to the anonymous delegate in C#.
Here are the results from the F# code projecting even numbers:
val evens : int list = [0; 2; 4; 6; 8; 10; 12; 14; 16; 18; 20]
Adding Anonymous Classes to the Projection
One nice feature about LINQ is that you can do a projection, and create an anonymous class on the fly to represent your projected item. For example, you could take the integer number list and project it to an instance of an anonymous class containing the number and its product.
var items = integers.Select(e => new { number = e, product = e * 2 }).ToList();
Notice that we didn't have to declare a new class containing those fields, C# generates it for us.
F# has an equivalent mechanism called Object Expressions. You can declare your anonymous class on the fly and then use it in your List projection as follows:
type Pair = {Number : int; Product : int;}
let productPairs = list |> List.map(fun e -> {Number = e; Product = e*2});;
F# just figures out from the type assignment that you are using the anonymous class defined in the type Pair in your lambda expression. Here are the results from the F# interactive window
[{Number = 0; Product = 0;}; {Number = 1; Product = 2;}; {Number = 2; Product = 4;}; {Number = 3; Product = 6;}; {Number = 4; Product = 8;}; {Number = 5; Product = 10;}; {Number = 6; Product = 12;}; {Number = 7; Product = 14;}; {Number = 8; Product = 16;}; {Number = 9; Product = 18;}; {Number = 10; Product = 20;}]
Getting Indexes from the Array
LINQ lets you automatically get the index of your list item in the select if you just pass the additional parameter as the first parameter in your lambda expression.
var odds = integers.Select((index, x) => new { Index = index, Product = x * 3 }).Where(o => o.Product % 2 == 1).ToArray();
The F# List library has equivalent functionality with a function called mapi. Here is how you could do the same thing in F#:
let odds = list |> List.mapi(fun index x -> {Number = index; Product = x * 3});;
I like the way F# broke out the index functionality into a new method, because it adheres closer to the single responsibility principle than LINQ does for this function.
The results of the mapi example are shown below
[{Number = 0; Product = 0;}; {Number = 1; Product = 3;}; {Number = 2; Product = 6;}; {Number = 3; Product = 9;}; {Number = 4; Product = 12;}; {Number = 5; Product = 15;}; {Number = 6; Product = 18;}; {Number = 7; Product = 21;}; {Number = 8; Product = 24;}; {Number = 9; Product = 27;}; {Number = 10; Product = 30;}]
Filtering
Another major use of LINQ is for filtering. LINQ uses a Where clause that takes a predicate to determine how to filter a list. Here is a LINQ expression for pulling out all the odd numbers from the integer list into an array:
var odds = integers.Where(o => o % 2 == 1).ToArray();
This LINQ statement will test each element in the integer list and see if when you divide by 2, the remainder is 1. If the remainder is not 1, the expression is false, and the item is not included in the list.
The equivalent statement in LINQ is almost identical, except for the piping again:
let odds = list |> List.filter(fun o -> o % 2 = 1)
What if I wanted to chain several filters together? That's where the piping comes in handy in F#. Let's say I wanted all odd numbers greater than 5. I could put it all in one expression or I could chain the filters together with the piping:
let odds = list |> List.filter(fun x -> x % 2 = 1) |> List.filter(fun x -> x > 5);;
You could also chain your select statement along with the filter. For example, the following returns a list of odd multiples of 3:
let odds = list |> List.map(fun x -> x * 3) |> List.filter(fun x -> x % 2 = 1);;
In C#, the same statement would be similar, where the chaining is carried out with the dot operator:

Join the conversation! Your thoughts help the community grow.