F# For C# Programmers: Programming In the Small

During CodeMash this past January, I had the opportunity to talk with Chris Smith about F#. One of the things that he considered to be a sweet spot for the language was programming “in the small”. At the time, I didn’t completely agree with his claim, but after writing more F# and functional C# code, I see where he was coming from.  Programming in the small is an important part of developing software, and it is an area where F# excels.

What is programming in the small?

Brian McNamara of the F# team has a great post where he describes how functional programming impacts code in the “large”, “medium”, and “small”. His post is well worth a read if you know a little bit about functional programming, but for those of you coming from a C# or Java background, I’ll summarize here. Programming in the small is the code that goes inside a method body. As Brian puts it, this is the code that actually “does stuff”. In this context, programming in the medium is code at the class/interface/module level, and programming in the large is code that spans multiple classes and interfaces. For the rest of this post, I’m going to focus on the programming in the small, but it’s good to put everything in context.

How does functional programming improve the code you write in the small?

Before we dive into F#, let’s start with techniques for programming in the small that are more familiar to C# developers. Consider the following code to square a list of numbers:

IList<int> values = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

IList<int> squaredValues = new List<int>(); 

for (int i = 0; i < values.Count; i++) 
{ 
    squaredValues.Add(values[i] * values[i]); 
}

In the C/C++ days, we were stuck with this. Although this is a simple algorithm, you can see that there is significant amount of overhead describing things that we shouldn’t have to bother with. Instead of saying “square each item in the list” we have to say “Make a new list. Then with each number from zero to the number of items in the list, index into the list with this number and square that value. Finally add that number to the new list”.

C#, like many languages,  gives us a better way to express this algorithm:

var values = Enumerable.Range(0, 10); 

IList<int> squaredValues = new List<int>(); 

foreach (int value in values) 
{ 
    squaredValues.Add(value * value); 
}

With a foreach loop, we can see that the code gets better.  Now we say “Make a new list. Then for each element in the input list, square it and add it to the new list”.

Now let’s take a look at a solution that uses a functional approach. No, we’re not going to write F# code yet. Instead, we’re going to write a LINQ query. We’re doing this because LINQ uses some of the functional techniques that makes F# great at programming in the small.

var values = Enumerable.Range(0, 10); 

var squaredValuesQuerySyntax =
    from value in values
    select value * value;

Now our code says “for each value in the list, square it” which is exactly what we were trying to describe in the first place. Even for this trivial example, we wrote less, cleaner code to solve our problem.

Now for F#. The last snipped of C# code is almost the same as what we would write in F# once we re-write our LINQ expression to use extension method syntax:

var squaredValuesExtensionMethodSyntax = values.Select(value=>value*value);

Now, here is the equivalent F# code:

let values = [0..10] 

let results = values |> Seq.map (fun value -> value * value)

In F#, we use the let keyword instead of var, the map function instead of Select, and the |> operator instead of using an extension method. Other than that, the flow of our code is the same as we did with LINQ.

The Story So Far

So, the question is, what makes the functional code above better?

The key observation is that the above code separates the looping algorithm from the squaring algorithm. It’s like we used dependency injection, but it happened at the method level- in the small, instead of at the class level.

Most programmers know that duplicating code is a bad practice, but while coding in imperative languages, many of us ignore that advice when writing loops. Loops are considered to be idioms, and somehow get a free pass from the Don’t Repeat Yourself rule.

Functional languages take a different approach. Instead of constantly re-writing for the same chunks of “simple” loop logic, they use small, single purpose functions to capture the common looping code. The advantage of this approach is twofold. First, you write less code to express looping constructs. Second, you can easily glue these small functions together to perform more complicated operations. It’s the same technique that makes the *nix and PowerShell terminals so powerful.

Going Further With F#

We’ve seen how using functional techniques can improve C# in the small, but what makes F# better at programming in the small? This question would take a book to answer, but here are a few reasons:

-Better library support. F#’s Seq module is far more robust than LINQ and offers many extra “glue” functions to help you stitch your code together.

-Better compiler support. Consider the following example:

public static int Square(int value)
{
    return value * value;
}

public void ProblemsWithTypeInference()
{
    var values = Enumerable.Range(0, 10);

    var results = values.Select<int, int>(Square);
}

We want to say values.Select(Square) without having to specify the type arguments. After all, the compiler has enough information to infer the types. Unfortunately, in C#, the code will not compile if we omit the generic type parameters. [UPDATE: The code will compile without the generic type parameters in C# 4.0. Still, there are a number of other areas where C#’s syntax lags behind F# when using functional techniques.] In F#, this code looks like this:

let Square x = x * x

let GoodTypeInference =
    [0..10]
    |> Seq.map Square

Aside from not having to specify the type of the map function (F#’s equivalent of Select), we didn’t have to specify the type anywhere else either. The F# compiler simply infers the types of each variable or method. This makes code inside the method body extremely concise and easy to work with.

-Functional constructs including option types, discriminated unions, pattern matching, and much more. If you’re coming from a C# background, you probably don’t know a lot about these constructs, but they truly separate F# from C# and were designed specifically to aid the functional style that makes programming in the small better. A few hours spent learning about even a few of these F# language features is well worth the time invested.

This entry was posted in C#, F#, Functional. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*
*