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# (and the upcoming F# 3.0)
- 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
F# standard libraries
Just like .NET base class libraries (often called .NET BCL), F# has its own standard libraries especially to create immutable collections including immutable generic lists. The libraries include operations such as map, filter, fold, unfold, and many more.
Begin with this chapter, all of the technical explanation will be mostly based on MSDN Library of VS 2010 SP1 and VS 2012.
Overview of local help documentation in VS 2010 and VS 2012
Using MSDN Library documentation, the standard libraries is named as F# core libraries under Visual F# documentation.
This is on MSDN help viewer of VS 2010: (after installing VS 2010 SP 1)
NOTE: I recommend installing VS 2010 SP 1. There are many worthy features to consider, such as the return of non-browser help viewer (alias Help Viewer 1.1), bug fixes, stability and performance improvement.
If you use VS 2012 (formerly VS 11) the Help viewer will be:
The content of those two is almost similar, but the organization of contents are different. Of course, VS 2012 content is newer.
Getting started section in VS 2010 is available:
Getting started is gone in VS 2012 MSDN help, but it’s essentially the same in the section of “Using Visual Studio to write F# programs” like below:
The standard library of this part focuses on F# 3.0 on Visual Studio 2012.
The namespaces are: (with description from MSDN)
- Microsoft.FSharp.Collections Namespace (F#): describes the F# collection namespace, including arrays, lists, maps, sequences and sets.
- Microsoft.FSharp.Control Namespace (F#): describes the F# control namespace, including support for asynchronous programming, message passing, and event-driven programming.
- Microsoft.FSharp.Core Namespace (F#): describes the F# core namespace, including core operators, attributes, and types.
- Microsoft.FSharp.Core.CompilerServices Namespace (F#): describes internal libraries used by the F# compiler.
- Microsoft.FSharp.Data Namespace (F#): describes the F# data namespace, which contains type providers for data access, as well as units of measure.
- Microsoft.FSharp.Linq Namespace (F#): describes the F# Linq namespace, which includes types that support F# query expressions.
- Microsoft.FSharp.NativeInterop Namespace (F#): describes library support for F# native interoperability.
- Microsoft.FSharp.Quotations Namespace (F#): describes the F# quotations library.
- Microsoft.FSharp.Reflection Namespace (F#): describes the F# reflection API, which extends .NET reflection to support F# types.
Those namespaces are very important, especially the Microsoft.FSharp.Core.
The Microsoft.FSharp.Linq focuses on LINQ on F#, which will be described in detail in part 7, Using LINQ in F#.
The Microsoft.FSharp.Data contains type providers and units of measure. Units of measure will be described in detail in Part 10, the data and type provider will be described in Part 13.
F# Collections in Microsoft.FSharp.Collections
The F# collections are all derived from IEnumerable and IEnumerable(Of T), just like those collections in .NET Base Class Library, But F# offer this trait: it’s immutable by default.
In F#, there are type definitions (the ones in MSDN Library and the type definition) and type abbreviations. Type abbreviations are types that function as aliases for types.
For example: seq<’T> in F# is type abbreviations for IEnumerable(Of T) (or IEnumerable<T> in C#). This makes coding more convenient, but you have to be sure that your type abbreviation are consistent and understandable by the rest of your software development team or your library user.
Type abbreviations in F#
Type abbreviations in F# can be declared using this syntax:
type type-abbreviation = type-name
For example, the type definition of seq in F# is:
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
A word of caution, there is this restriction about type abbreviations in MSDN Library:
Type abbreviations are not preserved in the .NET Framework MSIL code. Therefore, when you use an F# assembly from another .NET Framework language, you must use the underlying type name for a type abbreviation.
For more details on type abbreviations, visit MSDN LIbrary: http://msdn.microsoft.com/en-us/library/dd233246.aspx
Let’s get back to F# collections. I can describe F# collections with the references from MSDN Library, but that is available for all of you, my dear blog readers, to read and to try.
Looking at F# Collection description from MSDN, this is a table to describe F# collection:
Table (preformatted) above taken from: http://msdn.microsoft.com/en-us/library/hh967652.aspx
What about the corresponding type in .NET? To further quickly understand collections of F#, here is the comparable classes in .NET Base Class Libraries (BCL):
Map in F# can be compared with Dictionary<Key,Value> in .NET BCL but with added twist: it’s immutable in F#.
As noted above, an equivalent F# counterpart of List<T> in .NET BCL is ResizeArray<’T>, not list<’T> in F#.
A list in F# is an immutable single linked list, meaning that once you set the value you can’t modify it anymore. Do not confuse F#’s list<’T> with .NET List<T>!
Any operations on collections are defined in modules.
For example, map and filter operation of seq is defined in Seq module.
These are the list of modules in Microsoft.FSharp.Collections:
This part/chapter will not describe all of the module, as it only focuses on the most and widely used: Seq and List.
Seq module
Seq module contains mostly operations that has overall similar functionality with System.Linq.Enumerable but this feature has difference in the parameter. Seq module use F# delegate (in the form of FastFunc) with currying and higher-order function supports, rather than common Func delegate.
Common operations in Seq will be explained with Enumerable counterparts if available.
Creating sequences
Creating sequences in F# has these ways:
- create sequence expression
- using Seq.empty
- using Seq.singleton
- using Seq.Init
- using Seq.ofArray (create sequence from array)
- using Seq.cast to cast any IEnumerable to sequence
- create infinite sequence
Sequence expressions in F# is:
A sequence expression is an expression that evaluates to a sequence.
This can be confusing, but a sequence expression is simply a sequence to create a “seq” with a sequence of values.
Samples:
seq { 0 .. 20 }
It will create a sequence of 0 to 20.
Sequence with increments can also be created, like this sample:
// Sequence that has an increment.
seq { 0 .. 10 .. 100 }
It will create a sequence of 0 to 100 with increment of 10.
We can also create sequence by using more expressive for loop.
Simple for loop in sequence expression sample:
seq { for i in 1 .. 10 do yield i * i }
The yield can be replaced with “->” operator so “do” can be omitted, like this:
seq { for i in 1 .. 10 -> i * i }
There are also many samples to use from MSDN Library.
The following code uses yield to create a multiplication table that consists of tuples of three elements, each consisting of two factors and the product.
You can create empty sequence using Seq.empty.
The sequence created by Seq.empty can be created with generic type or by using concrete type parameter.
Sample:
let emptySeq = Seq.empty
let emptySeqString = Seq.empty<string>
We can check the type using F# interactive to proof the resulting generic sequence, like the below screenshot:
Now, we are going to create sequence using Seq.singleton. The purpose of Seq.singleton is simple: we want to create a sequence that only has one element.
Sample:
let seqOne = Seq.singleton 10
Using Seq.Init is simple. Seq.init will create sequence using function expression, therefore give you more expressive power, not just using for in a sequence expression before.
The sample is:
let seqFirst5MultiplesOf10 = Seq.init 5 (fun n -> n * 10)
Seq.iter (fun elem -> printf "%d " elem) seqFirst5MultiplesOf10
The result will be:
0 10 20 30 40
This is the screenshot:
To create sequence from an array, use Seq.ofArray from an array, or you can use pipeline.
// Convert an array to a sequence by using Seq.ofArray.
let seqFromArray2 = [| 1 .. 10 |] |> Seq.ofArray
Creating a sequence from existing IEnumerable is possible by using Seq.cast.
The signature of Seq.cast is: (from http://msdn.microsoft.com/en-us/library/ee370344.aspx)
Seq.cast : IEnumerable -> seq<'T>
A sample of Seq.cast to create sequence ftom weakly typed ArrayList:
let mutable arrayList1 = new System.Collections.ArrayList(10)
for i in 1 .. 10 do arrayList1.Add(10) |> ignore
let seqCast : seq<int> = Seq.cast arrayList1
To create infinite sequence, you can create infinite sequence by using Seq.initInfinite.
According to MSDN LIbrary, this is the explanation from Sequence page:
For such a sequence, you provide a function that generates each element from the index of the element. Infinite sequences are possible because of lazy evaluation; elements are created as needed by calling the function that you specify. The following code example produces an infinite sequence of floating point numbers, in this case the alternating series of reciprocals of squares of successive integers.
The best way to understand this is by looking at the sample:
Sequence operations
Other operation of Sequence is: (with the corresponding LINQ’s Enumerable equality)
- Seq.average (the concept is equal to Enumerable.Average with no parameter
- Seq.averageby (the concept is equal to Enumerable.Average with delegate as parameter)
- Seq.pairwise
- Seq.windowed
- Seq.map (the concept is equal to Enumerable.Select)
- Seq.filter (the concept is equal to Enumerable.Where)
- Seq.iter
- Seq.iteri
- Seq.sort
- Seq.sortby (the concept is equal to Enumerable.OrderBy)
- Seq.groupby (the concept is equal to Enumerable.GroupBy)
- Seq.fold
- Seq.unfold (the opposite conceptual of Seq.fold)
- Seq.distinct (the concept is equal to Enumerable.Distinct)
- Seq.reduce
- Seq.scan
- Seq.sum (the concept is equal to Enumerable.Sum with no parameter)
- Seq.sumby (the concept is equal to Enumerable.Sum with delegate as parameter)
Those are commons operations of Seq modules, as in F# 3.0 in Visual Studio 2012, and it’s the same in F# 2.0 (in Visual Studio 2010). Future version of F# may have additional features or functionalities.
Seq.pairwise has interesting operation:
Returns a sequence of each element in the input sequence and its predecessor, with the exception of the first element which is only returned as the predecessor of the second element.
But simply the result of Seq.pairwise is a tuple with 2 element that defines pairs.
To understand it well, see Seq.pairwise in action:
Seq.pairwise and Seq.windowed has the same transformation result, but Seq.windowed produces an array of paired elements.
Seq.iter, Seq.iter2 and Seq.iteri will enumerate a sequence and do something for every iteration, this is why it named with “iter”. Consider it’s the same as “for each” in C# and VB but with functional approach.
Seq.iteri is a special case, it will give information of the current index of the sequence as parameter for the operation (both Seq.iter and Seq.iteri will need function to perform operations).
This iteration is simply encapsulating side effects as it has no relation on changing the member or element value of the sequence.
Sample of Seq.iter:
printf "Seq.iter: "
Seq.iter (fun (a,b) -> printf "(%d, %d) " a b) (seq { for i in 1..5 -> (i, i*i) })
There’s no equal implementation of Seq.iter, Seq.iter2 and Seq.iteri in .NET BCL, but you can create it easily on your own with delegates.
List module
This section is not just describing List module in F#, but this section will also provide basic list in F# conceptually.
A list in F# is an ordered immutable list of element with the same type. A list has index, therefore enumerating a list can go forward and backward or simply going to a specified location by using index.
Creating lists
You can define a list by explicitly listing out the elements, separated by semicolons and enclosed in square brackets, as shown in the following line of code:
let list123 = [ 1; 2; 3 ]
Declaring the value of a list must be enclosed in “[..]” pair. This is different when defining array in F#, an array has to be enclosed in “[| … |]”.
Not just in a single line, you can also put line breaks between elements, in which case the semicolons are optional. The latter syntax can result in more readable code when the element initialization expressions are longer, or when you want to include a comment for each element.
Sample:
You can also create F# list with type mentioned explicitly and also the element can contain the same type of objects or derived objects.
Sample:
let myControlList : Control list = [ new Button(); new CheckBox() ]
Unfortunately, F# does not support covariance and contravariance like those in C# and VB, although .NET CLR supports it as well.
You can also create List in sequence expressions just like in creating sequence.
Sample:
let squaresList = [ for i in 1 .. 10 -> i * i ]
Again, all list in F# is immutable.
Operators for working with Lists
Lists can be concatenated as long as the types are the same by using the "@" operator, for example:
let list3 = list1 @ list2
You can attach elements to a list using :: (cons) operator. Again, the elements type has to be the same.
For example:
let list2 = 100 :: list1
List properties
These are common properties of a List:
List in F# can be used and accessed using List properties of Head and Tail, in the form of pattern matching.
For example below, the code will recursively sum the head with the rest of the elements:
You can also iterate a list with index and do additional side effects with List.iteri.
Operations in List are essentially the same as in Seq modules.
Overview of Microsoft.Fsharp.Core and Microsoft.Fsharp.Core.CompilerServices
Basically, these namespaces are the core of F# language infrastructure.
This namespace of Microsoft.Fsharp.Core contains functionalities, including language primitives, operators, attributes, primitive types, strings, and formatted I/O.
These are the modules in Microsoft.Fsharp.Core with the explanations:
The equivalent class for Printf module in .NET BCL is Console, with the exception of bprintf that print to StringBuilder.
The format of the string format to be used as output is not the same as formatting in Console, because the syntax is different.
Sample printf:
printf “Hello world”
With format:
printf “number is %d” 5
This is the list of formats:
Microsoft.Fsharp.Core.CompilerServices contains some internal functions for use by the F# compiler, and also types for implementing type providers.
Further reading
- MSDN Library on Sequence: http://msdn.microsoft.com/en-us/library/dd233209.aspx
- MSDN Library on F# standard library: http://msdn.microsoft.com/en-us/library/ee353567.aspx