Hello there!
This blog of F# contains full (long) blog posts of adventure in functional programming and F#. I call it adventure, because I’ll try to make F# as fun to as possible to learn.
NOTE:
This blog is starting to use Visual Studio from Visual Studio 2012 and Visual Studio 2013 (from Release Candidate to RTM), and provide hints of F# 3.0 in Visual Studio 2012.
Now, here are the parts:
- Part 1: Introduction to Functional Programming
- Part 2: Functional Programming Concepts
- Part 3: Introduction to F#
- Part 4: Functions, Delegates and Computation expressions in F#
- Part 5: F# standard libraries
- Part 6: OOP in F#
- Part 7: Using LINQ in F# (you are here)
- Part 8: F# Asynchronous workflow
- Part 9: F# MailboxProcessor
- Part 10: Units of Measures
- Part 11: F# Power Pack
- Part 12: F# for Silverlight 4 (and above)
- Part 13: A look at F# 3.0 in VS 11 (Visual Studio 2012)
- Part 14: A look of Functional Programming in VB 10 and C# 4.0 compared to F#
- Part 15: A look of F# compared to Haskell, Scala and Scheme
- Part 16: F# future and what features that F# must have
- Part 17: Retrospective
Using LINQ in F# 3.0
Before F# 3.0 in Visual Studio 2012, LINQ was not available in F#. If you use F# Powerpack for F# 2.0, LINQ was implemented as computation expression.
An overview of LINQ
LINQ stands for Language INtegrated Query. LINQ has its first release in C# 3.0 and VB 9.0 in Visual Studio 2008.
Basically, LINQ is a syntactic sugar on top of C# 3.0 and VB 9.0. It is then translated by the compiler into a series of extension method calls to Enumerable (for LINQ to Object) or Queryable (for LINQ to SQL, LINQ to Entity).
Let’s look at LINQ to Object, because this is the basic foundation of all other LINQ to others.
LINQ to Object is the basic foundation because it is available for the basic foundation of all generic or typed collection in .NET: IEnumerable<T>
Why? There are always misconception that LINQ is a mean to connect to database, and the fact is not that! LINQ is a way to query a collection of data. The data can be a single type or can be a collection.
I can also query the running processes on my machine that consumes memory more than 1 MB: (using C#)
In VB, we can also do that:
Now we can prove that LINQ is not used only to query database.
The interesting point of using LINQ is, the from, where, select is used as keywords. The compiler will translate those LINQ keywords into series of Lambda expressions.
In C#, the code will be translated into: (the commented is the original source code)
If you see the source code very well, you’ll also notice that there are type inferences in action! But the type inferences in C# and VB are different with F#.
In C# and VB, type inferences are happened in local scope, and also for method’s parameter but not for the method return type.
F# will deduce an infer the return type of the method gracefully and flows nicely outside the scope of the methods.
F# 3.0 LINQ query expressions
Let’s dive into F# 3.0 LINQ!
LINQ in F# 3.0 was composed using monad builder, by a class names QueryBuilder. The complete fully qualified class name is Microsoft.FSharp.Linq.QueryBuilder. Don’t worry, you don’t have to use it directly because it’s composed for us to be used nicely as composable query.
In F# 3.0 the code will be:
The interesting aspect is the use of Seq.ofArray. Let’s say we’ll delete the use of Seq,ofArray, run the code, and display the result using the F# interactive:
Now with Seq.ofArray added, the result is much simpler and also nicer to observe:
Without Seq.ofArray, the F# interactive will display all of the resulting array of Process.GetProcesses after it display the result of running process. Because the basic behavior of GetProcesses is eager evaluation, not lazy evaluation. Seq.ofArray pipeline will execute it lazily, only evaluate it as needed.
The type inference will infer that array of Process is a derived from IEnumerable<Process>. It is also true in C# and VB.
In the F# code, I also use sortByDescending to sort the result descending, based on the size (using property of WorkingSet64). It is equal to order by in C# and VB with descending option added.
What about the semantic? The semantic is the same, only few clause has different semantic.
This is the table of semantic and syntax differences between C#, VB and F#:
Notes:
All of the aggregates are not available in LINQ of C# and VB in a query comprehension. F# has integrated in the query computation, as with other SQL clauses (FROM, SELECT, WHERE, JOIN, GROUP BY).
Those query operations that has no semantic differences are really having the same calls to the same methods of LINQ to object. Having no semantic differences means that it’s guaranteed for F# to have the same results as in C# and VB.
We have known SELECT, WHERE, and ORDER BY in F# and a hint of “take”. They are very simple to use, and it has the same semantic although the syntax of ORDER BY in F# has different name, using sortBy.
This is F#’s groupBy in action:
(I intentionally group the processes by ProcessName, and then display the number of grouped process)
As usual, svchost has the largest number of instances.
Note:
The groupBy sample has Count(), and this require System.Linq.
Iterating the result of group by requires us to look at the Key collection first, then the grouped data. Why?
Due to the returned result of groupBy is the same as Enumerable.GroupBy, that returns a IDictionary<Key,Value>.
It returns a dictionary because of the nature of group by: the result is grouped by a key, then each key will have values that grouped by the key.
Now, I’m going to display the maximum amount of memory taken by those process.
This is the code using maxBy:
Those equalities of query operators table is not displaying all, actually. But it can be considered the same as the operations in System.Linq.Enumerable extension methods.
Further readings
- F# query expression in VS 2012: http://msdn.microsoft.com/en-us/library/hh225374.aspx
No comments:
Post a Comment