Getting Functional with F#

Today, .NET developers using only Microsoft’s solutions have the chance to use Visual Basic, C#, and C++ to develop their applications. All three of these languages are based on a programming paradigm (model) called imperative programming where you as a developer specify the exact steps to solve the problem at hand. This is done by using statements in the correct order, but also with the help of variables and instances of classes to store the state of the application.

Although this model of programming is very useful in many situations (outside the domain of programming, furniture assembly instructions and cooking recipes are also examples of imperative programming), it is not the best method for every task. This is the reason functional programming was developed.

Functional programming is closer to the mathematics you learned at school than languages such as C#. However, this is not to say that functional languages are useful only for calculations. In fact, you can do all the same things in functional languages such as F# as you can do with C#. Only the way you do it differs.

In functional languages, the main question is what kind of data you need, and what should be done with the data. Furthermore, in functional languages, the concept of a function is fundamental. As you will soon learn, this also means that maintaining state is not important anymore. Contemporary examples of functional programming languages include XSLT, LINQ, and of course, LISP. For .NET developers, F# is the new kid in town.

Introducing the F# Language

F# started as a research project of Microsoft Research, and since then has grown to become the most probable candidate of being the first functional language to be included with Visual Studio. Although the term functional might in your mind be somewhat a limiting factor, the good thing about F# is that it supports object-oriented constructs, and also has full access to the .NET Framework.

If you are familiar with languages such as C#, you might at first find that F# is at the same time both familiar and unfamiliar to you. For instance, if you wanted to print out an array of numbers multiplied by two in F#, you could write code like this:

let timesTwo x = x * 2
let numbers = [1; 4; 5; 7; 12]
let numbersTimesTwo = timesTwo numbers
printfn "Numbers = %A" numbersTimesTwo

These four lines introduce you two important concepts in F#: defining functions and lists, and standard functions of the language such as Of course, if you wanted to write the canonical “Hello, World” example, the “printfn” function would be your best friend.

Another typical example of functional languages is the way functions are created and used. Consider the following example to calculate the factorial (factorial is the product of numbers from 2 to n, so that, for example, 5! equals 2*3*4*5 = 120):

let rec factorial n = if (n = 0) then 1 else (n * factorial(n-1))
let x = 5
let f = factorial(x)
printfn "%d! = %d" x f

In functional languages, recursion is used instead of regular loops, and F# is no exception. In both of the above code listings, the first code line defines a new function with the “let” keyword. In the second example (above), the “rec” word tells F# that the function “factorial” is used recursively. Here is another listing, which finds numbers in an array that are larger than five:

let numbers = [1; 4; 5; 7; 12]
let largeNumbers = List.filter (fun x -> x > 5) numbers
printfn "Large numbers = %A" largeNumbers

Here, the List.filter function takes a function parameter (defined with the “fun” keyword), and executes it for each element in the list. Compare this to a snippet of C# code with LINQ:

int[] numbers = { 1, 4, 5, 7, 12 };
var largeNumbers = numbers.Where(n => n > 5);
foreach (int num in largeNumbers)

As you can see, functional programming code looks familiar, but at the same time also can get a little used to, especially if you compare it to the rather straightforward manner of many C# applications. Even though functional languages in general are their best in algorithm implementations and in sectors such as financing, statistics, and mathematical research, F# can be used in much broader ways.

Consider, for example, the following code to retrieve the latest USD to Euro exchange rate from the European Central Bank (ECB). To use the code, you need to add a reference to the System.Xml.dll assembly file in your solution:

let ecbXmlUri = "
let xpathNavi =
let resolver = System.Xml.XmlNamespaceManager(xpathNavi.NameTable)
let xmlNsEcb = "
let xmlNsGm = ""
resolver.AddNamespace("ecb", xmlNsEcb)
resolver.AddNamespace("gm", xmlNsGm)
let nodePath = "/gm:Envelope/ecb:Cube/ecb:Cube
   /ecb:Cube[@currency = 'USD']"
let node = xpathNavi.SelectSingleNode(nodePath,resolver)
let rate = node.GetAttribute("rate", "")
printfn "USD to Euro exchange rate is: %s." rate

As you can see from this listing, you can fully utilize the .NET Framework in your F# applications. In fact, you could view F# as a hybrid language, supporting both functional and imperative constructs. The above code would look much the same if it had been written with C#, for instance.

That said, classes, objects, and interfaces can all be used in F#. The language lets you build your own classes and interfaces as well. By the way, note some interesting syntax in the above listing. For instance, long strings can be split into multiple lines with the backslash character.

A (Parallel) Database Example

The previous listing gave you a hint that the whole .NET Framework versions 2.0 and later are accessible from F#. Now, assume that you would like to build a simple database application to read data from an SQL Server database. As you are surely aware, using ADO.NET is usually the best solution to do this, and so you would use the connection, command, and reader (for instance) classes from the System.Data.SqlClient namespace.

Here is an example of how to read data from the old, yet familiar Northwind database:

let connStr = "Data Source=.;Initial Catalog=Northwind;
               Integrated Security=True;"
let conn = new System.Data.SqlClient.SqlConnection(connStr)
let sql = "SELECT [employeeid], [firstname], [lastname]
           FROM [employees]"
let cmd = new System.Data.SqlClient.SqlCommand(sql, conn)
let reader = cmd.ExecuteReader()
printfn "Name = %s %s" (reader.GetString(1)) (reader.GetString(2))

Again, F# provides a quite straightforward way of accessing data with ADO.NET. As you can see, it is easy to convert C# code to F#, because the classes and methods calls you need to make stay the same.

Of course, things get more interesting for F# if you add some calculations into the mix. For instance, you might need to calculate the price of items with sales tax included. To retrieve the data from the database, you could use, for example, a LINQ query to get two arrays of values: one for the prices and another for the tax percentages for the given prices:

let prices = [100.0; 200.0; 50.0]
let taxPercents = [5.0; 4.0; 7.0]

With these two arrays, it would be simple to define a function called “calculateTax” that would calculate the correct price, and then run a List.map2 (“map2” is the method version that takes two parameters instead of just one) on these two lists:

let calculateTax price tax = price * (1.0 + (tax/100.0))
let results = List.map2 calculateTax prices taxPercents
printfn "results = %A" results

This would return a new array, “results,” with values [105.0; 208.0; 53.5]. Of course, all this works nicely, but wouldn’t it be great if you could somehow make this calculation use multiple threads to take better use of modern multi-core processors? With F#, this is almost as easy as 123!

F# supports built-in parallelism, and the “async” keyword. If you wanted to calculate the taxes in parallel, you would embed the List.map2 method call into an asynchronous context:

let results =
   Async.Run (Async.Parallel [
   async { return List.map2 calculateTax prices taxPercents } ])

That is all you need! Of course, with only three elements in the array, it would actually take longer to calculate the taxes in parallel because of threading overhead, but if you would have three hundred thousand items instead, the differences would start to show.

More by Author

Must Read