When I was at DevLink last week I gave a talk designed to specifically identify why and when you should use F#. I was going to post the slides, but then I realized that they are in the form of a ‘presentation deck’ rather than a ‘reading deck’. So rather than having a few vague slogans and images in a .pptx file, I’ve transcribed my talking points. So imagine a deep and sexy voice narrating this blog post aloud. I’ve indicated where I ‘break character’ in the transcription.
Hello, my name is Chris Smith and I work at Microsoft on the F# team.
[Ed. I wish every talk started with a slide like this.]
Of all the talks I’m giving at DevLink, this is the one I am looking forward to the most. This talk is really the one people should be giving at conferences. There certainly is a lot of excitement surrounding F#, but the question on most people’s minds is does it matter to me? I think we can assume that F# has to be good at something, because it if it wasn’t why would Microsoft be spending so much time and energy putting it into Visual Studio 2010?
So this talk is about removing some of the excitement associated with your typical F# talk and just deal in facts. My goal isn’t to convince you to start programming in F#, but instead articulate what the language is good at so you can decide for yourself if F# is worth looking into.
If you’re super-happy writing C# or VB.NET code then you really have no reason to learn F#. Just keep on being happy 😉 But if you find yourself struggling to write your .NET code, then perhaps F# is what you’ve been waiting for.
Let’s begin with some F# Facts:
- False. F# isn’t going to replace C# or VB, ever. F# is just different, so it makes some things easier and some things harder. But the point is that with F# you have a choice – and this talk is about highlighting some of the situations where F# may make more sense than C#.
- False. While F# (and other functional languages) make it easier to parallelize your code, it doesn’t do it for free. In fact, you can write the same deadlocks and race conditions in F# than you can in C#. Just in F# is that you have to point the gun at your foot first.
- False. Functional programming is enjoying a lot of attention these days with new languages like Erlang, Scala, Nemerle, Haskell, etc. However the core ideas of functional programming have been around for quite some time without ever ‘making it big’. I don’t see functional programming becoming the one true paradigm that everyone will switch to. Rather, I see it as a great way for solving a specific class of problems. F# is a hybrid language, so it allows you to write code in the paradigm that makes the most sense for the problem at hand.
- True. Absolutely.
- False. In the keynote at DevLink Josh Holmes specifically called this out as being a bad idea. Not to say that F# + ASP.NET isn’t a good idea, but that using new technologies for the sake of using new technologies makes things harder than they have to be.
Bottom line is this: you should learn what F# is about, and if you’ll be more productive using it then do so. Otherwise, go with what you know.
[Ed. This slide’s pretty self-explanatory.]
- As I mentioned before, F# is a multi-paradigm language. You can write functional, imperative, and object-oriented code in it. This allows you to be pragmatic instead of trying to constrain every problem you see into classes and interfaces.
- F# is a type inferred language, leading to succinct programs. Think of how much time you spend adding type signatures, semicolons, and curly braces to your favorite programming language. All that information is just a crutch for making it easier to write the compiler. Why not write just the code you want and let the compiler figure out the rest? You’ll see later why I think F#’s succinctness is it’s greatest strength.
- F# is a .NET programming language. It compiles down to IL and the same runtime as C# and VB. So F# will ‘just work’ with your existing .NET code and have the same performance profile as C#.
- F# will be ‘in the box’ for Visual Studio 2010,but is also available now as an add-in for Visual Studio 2008.
- It features a REPL like Ruby and Python, called the F# Interactive window - you’ll see that in action shortly.
It’s easy to get overwhelmed with all the details of a new programming language. The one thing I want you to remember about F# as a whole is that it is fun. F# eliminates a lot of the hassles associated with programming allows you to focus on just writing the code you care about.
[Ed. This is the part where I give a quick demo of F# in Visual Studio. The main features are:
- Creating new projects
- The F# Intellisense experience
- Hovering over a local value shows its type information
- The F# Interactive window
It is important to note that F# supports nearly every feature that C# does. So when you use F# it isn’t an all-or-nothing type of proposition. You don’t have to throw away your existing code and move everything over to F#. In fact, we expect F# code to primarily be used as a class library integrated into a larger software package. Perhaps some backend server component is written in F# while the rest of your code remains in C#/PHP/Smoke Signals/whatever.
Being able to seamlessly interoperate with .NET opens up a lot of possibilities for F#. Not only can you take advantage of existing tools like the Visual Studio debugger, but also other .NET platforms such as using XNA to run F# code on the X-Box or Silverlight to run F# code on the web. This synergy is perhaps the main reason why F# get’s much more attention than earlier functional programming languages like OCaml. OCaml’s great, but does it come with a world-class debugger, visualization libraries, and 3rd party ecosystem?
So I’ve been talking up F# a bit – bla bla .NET interop – bla bla F# makes programming fun. But why should bother learning a new language?
Let’s start by looking at some of the buzzwords associated with F#.
- Statically typed. F# is a statically typed language, in contrast with Ruby which is dynamically typed. This means that type information is known at compile time. So while you can’t do things like monkey patching in F#, code executes much faster and you’ll know about most errors at compile time.
- Succinct. In addition to being type inferred, F# is also whitespace significant. So if you tab a few lines of code under an if-statement, the compiler will treat that as the body of the if-statement. This saves you the burden of littering your code with curly braces as well as saves you vertical whitespace. Less code on the screen means you can see more of your program at a time, meaning you do less context switching while you look through code. It may not sound like much, but this will be a large boon for your productivity.
- Scalable. This isn’t talking about data centers or web servers, but just that if you apply solid software engineering principles to F# code you can write enterprise level applications. (Which is a fancy way to say that F# is not a ‘write-once’ language.)
- Explorative. In F# you don’t need to commit to a design in order to see how things work. You can rapidly prototype solutions in F# as well as experiment with algorithms and approaches in the F# Interactive window. Building on F#’s succinct nature, you don’t need to make a lot of code investment to experiment with your programs.
- Libraries. F# comes with its own library for writing functional code and more.
Functional programming has been around since the 1950’s (LISP) – so why is functional programming so important now? A lot of people will say things like how immutability helps in writing parallel programs, which IMHO isn’t that big of a deal. Because if you wanted to get serious about parallel programming there are programming languages designed to do that and only that exceptionally well.
The benefit of functional programming lies in what is referred to as programming in the small.
Think about the current state of the art when it comes to writing software: object-oriented programming. The main way we approach the ask of converting an algorithm into code is by breaking it into objects, effectively modeling the domain through classes and behaviors. That’s programming in the large. This process of abstraction works great for modeling large systems and breaking it down into smaller and smaller layers, but eventually you run into a wall.
What about the method bodies? The actual code that goes inside those classes? That’s programming in the small. The problem with object-oriented programming is that when you are writing algorithmic type code, it doesn’t make sense to create classes and interfaces. When you are programming in the small all you really care about is data transformation and raw computation.
Think of object-oriented programming as a baseball mitt, it’s great for a catching pop fly but certainly isn’t that useful for catching a football. To do that you need a little more finger dexterity. Functional programming is all about programming in the small. It emphasizes the manipulating data that needs to be preformed without all the overhead of classes and an arbitrary type hierarchy.
[Ed. This animated slide doesn’t look nearly as awesome when you print it out :-/]
The first area that F# really excels in is technical and quantitative computing. AKA number crunching.
Simulation is one area that F# would we well suited for – imagine you are writing some sort of physics simulator, or trying to model some real-world situation. In F# you can write the functions you want cleanly without needing to force a code-based abstraction onto the real-world processes.
Another aspect of simulations which makes F# a good fit is a feature called units of measure, which allow you to encode units such as ‘feet’ or ‘meters per second’ into the actual F# type system. So you’ll get a compiler warning if you try to add acceleration to a velocity. This allows you to eliminate an entire class of bugs.
Some F# early adopters are in the computational finance business. These firms have large codebases for automated stock trading, calculating risk, and so on. (Exactly the sort of computerized finance that caused the current global economic PITA 😉 F# allows these investment banks not only a way to express their financial models in a simpler and more declarative way, but also integrate with the rest of their software stack through .NET interop. (For example, farming out intensive computations to multiple machines through a COM-service or the like.)
Large Scale Data Processing
Finally, F# does a good job at data-exploration type problems. For example, imagine you were trying to mine some customer data to identify trends. In F# you can simply play around with your data in the F# Interactive window, no need to litter your machine with dozens of throw away projects. Also, using F#’s succinct programming model the cost of failure – refactoring or rethinking your approach – is much lower.
Next up is language oriented programming. Which generally means blurring the line between a programming language and natural language.
If you wanted to be all hardcore about creating domain specific languages, why not go ahead and write your own parser? Built into the F# PowerPack library are FSLex and FSYacc, two great tools for creating custom parsers. In fact, the F# compiler’s parser is built using FSLex and FSYacc.
Augmenting F# Code
Another great example of language oriented programming is the use of F# computation expressions. This is a high-powered language feature that allows you to write normal F# code and customize how it gets executed. For example, let’s say you wanted to write some F# code to interact with a robot on Mars. Rather than writing a ton of boilerplate code to retry every command you send to the rover – in the case of cosmic interference or Martian uprising - why not write an F# computation expression (AKA F# workflow) to automatically retry any F# code several times until it times out or succeeds.
[Ed. This is a pretty advanced topic that I’ll need to devote an entire series of blog posts to later.]
Creating New Languages
Another area F# excels in is creating internal domain specific languages (mini programming languages embedded in your F# code). F#’s discriminated union types makes declaring ASTs (or any other tree-like data structure) very simple.
Quotations (Expression Trees)
Finally, F# has the same Expression Trees feature found in C# and VB.NET. This allows you to get ‘compiler generated’ form of F# code, which with the right libraries, can allow you to defer the execution of that F# code to other platforms. For example, on a SQL server or on your video card’s GPU.
F# is also good at parallel programming, which to be pedantic is referring to the: parallel, asynchronous, concurrent, and reactive programming domains. F# doesn’t automatically parallelize your code, nor have any built-in support for parallel primitives. Instead, it has a couple of features that make parallel programming easier – but none of them are a silver bullet.
Immutable by Default
In F#, like most other functional programming language, data is immutable by default. So if you program in the purely functional paradigm you don’t have to worry about race conditions when executing multiple threads because there is no shared, mutable state for two threads to fight over.
Parallel Extensions to .NET
This isn’t an F#-specific feature per-say but will go a long way towards making it easier to write parallel programs and that is the Parallel Extensions (PFX) to .NET found in CLR 4.0. While the PFX adds a lot of great capabilities to the .NET platform, there are two parts in particular I am super-excited about.
The Task Parallel Library (TPL) is a set of classes for abstracting the process of spawning ‘tasks’ of work. With the TPL there is no longer any need to spawn or manage threads manually. Instead, you can trust the TPL ‘goo’ to deal with that for you as well as modulate how many threads are currently asking for CPU time to make sure you aren’t overwhelming your system with parallel tasks.
The other, and perhaps even more exciting, part of the PFX is the set of new Concurrent Data Structures. These are a new set of collection types that are built specifically with high-performance parallel applications in mind. So rather than sweating all the details of sharing mutable state, you can just have two threads writing to one of these concurrent data structures and all the messy locking and unlocking of data is taken care of for you.
You may have heard somewhere before that F# makes asynchronous programming super easy, that is 100% true.
The way to write asynchronous programs on .NET is through the use of the Asynchronous Programming Model or APM. This is a pattern where you begin an asynchronous operation – such as reading a file – by calling BeginOp (e.g., BeginRead) and passing in a callback. When the asynchronous operation completes, the callback is executed in which you must call EndOp (e.g., EndRead).
While this approach has served .NET well for nearly a decade it’s a huge pain in the ass to deal with.
- Passing state across callbacks is tedious and error prone
- You cannot easily handle exceptions if your asynchronous code is spread across myriad callbacks
The code in the slide is from the Microsoft Patterns and Practices group and is the recommended way for processing a series of images in parallel. If anything, I want to point out that there is a lot of code which doesn’t look that easy to write.
This is how to write that same code in F#, using the F# Asynchronous Workflows library. Like I’ve said many times, F# wasn’t created specifically to write parallel programs. F# Asynchronous Workflows is simply some functionality built into the F# library that makes asynchronous programming very easy. This is enabled through a feature called F# Computation Expressions.
In the code you see the ‘let!’ and ‘do!’. The F# Asynchronous Workflows library completes these operations asynchronously, doing all that jazz with thread hopping and callbacks behind the scenes.
So I have told you all about how awesome F# is, but let’s try to bring the discussion back down to reality. Certainly F# isn’t all unicorns and rainbows, right?
[Ed. I should probably get a better slide title from the marketing department 😉 ]
F# isn’t great for everything, here are a few such areas.
In F# v1.0 we won’t support any code generators in the box. So you won’t get any of the WYSIWYG editors for WinForms or WPF in F#. So if you want to write presentation layer code in F# you’ll need to unfortunately do it all by hand. However, this isn’t the end of the world because of F#’s .NET interop story. You could just as easily create your UI in C# or VB and simply call into your F# code through a class library.
Object Oriented Hierarchies
Even though F# can write object-oriented code, that isn’t the language’s main paradigm so when writing the heavily OO code of can look a little strange. Also F# supports many functional programming constructs that C# and VB don’t, such as discriminated unions and function currying. So if you created an F# library that exposed ‘functional’ code, it certainly wouldn’t look right if you tried to bring that into a non-functional language.
The key here is to properly encapsulate your F# code – programming in the small – when you want to integrate it with a larger component – programming in the large.
So what happens if F# does make sense for part of your application? Are you going to need to hire a bunch of rocket scientists? No. Actually, I’ll even go on record and bust out a hearty hell no. F# isn’t just for eggheads. In fact, this summer we’ve had a highschool intern working on some F# samples. (That’s right, someone who just graduated highschool writing F# code for their internship.)
There is nothing inherently difficult with functional programming, it’s just a different way to view problems. But pay attention to what your team says while they are learning F#:
- “It’s just like C#”. This means they are doing it wrong. The whole point of F# is that it provides you a different way to think about programming, and in that different approach be more effective. If you write C# code in F# you won’t be gaining anything.
- “F# is too simple for real-world problems”. While F# is a simple programming language to learn, you can accomplish quite a lot through just writing simple functions.
- “Functional programming hurts my brains”. This means you are on the right track. Learning F# will expose you to different approaches to solving problems. (functional v imperative, functional v object-oriented, etc.)
Even if F# will help you be more productive writing code today, what is the long-term cost of that F# code?
Well one great benefit of F# is that it is terse. I mentioned this before, but when you are trying to debug an issue being able to see all the relevant code on the screen at once you don’t have to constantly be context switching between different code files.
It can be said that mind-bending functional code is harder to understand than more normal imperative code. That’s totally true – but the reality is that you shouldn’t write mind-bending functional code in the first place. (Just like you shouldn’t write mind-bending code in any programming language.) Idiomatic F# code is clear and readable. You can certainly use features like function composition and function currying without making the code ‘write once’.
The bottom line is this: if you are happy with C# or VB, then just keep using them. In fact, ignore F# all together. You can benefit from learning F# like any programming language to make you a better programmer, but don’t switch to F# if there isn’t a specific reason.
But if you find that you are struggling against your programming language to express your ideas. That you find too much syntactic clutter gets in the way, then check out F#. In domains where there is a lot of computation or data transformation to perform – technical computing, language oriented programming, parallel / async – you might be more productive.
Writing code in F# doesn’t magically make it faster or take up less memory. All it does is provide you with a different way to view the problem space, and in that different view be more effective in encoding algorithms to solve your problems by giving you more ways of expressing your ideas. (That is, in an imperative, object-oriented, or functional style.)
Unlike a lot of ‘awesome new technologies’ coming out from Microsoft, you can actually use F# today. In fact to my knowledge there are a growing number of developers who are paid to write F# code every day. You can find the latest F# CTP, which is an add-in for Visual Studio 2008, from the F# Dev Center at http://fsharp.net. I you want to try even fancier new technologies, you can also check out Visual Studio 2010 Beta1 from http://msdn.com.
For non-windows folks you can F# via Mono at http://mono-project.com.
For learning F# I recommend the three B’s: Books, Blogs, and Bugging other people.
For being a language that hasn’t officially come out here there are already several great books on the subject. The most recent general book on F# was Expert F# by Don Syme, Adam Granicz, and Antonio Cisternino. It’s a good book, but it’s main drawback these days is just when it was published: 2007. Since then the language has undergone some significant revision, especially in the F# libraries.
I – in my completely unbiased opinion – recommend you wait until early November and buy my book, Programming F# from O’Reilly. 🙂 It is a comprehensive guide to the F# language. In it you won’t find a lot of theory, but instead a clear introduction to what F# has that your favorite language doesn’t, and how you can take advantage of those features.
There is a great F# community online with a ton of high-quality blogs. In fact nearly everyone on the F# team has their own blog. Check out the F# Development Center where you’ll find an aggregated feed for F# blogs.
Bugging other people
Finally, there are two great places to go for learning more about F#. http://hubfs.net is the Hub FS website, a great forum dedicated to exclusively F#. In addition, there has been growing interest in F# on http://stackoverflow.com. I recommend you ask questions there so that I may answer you and receive glorious reputation. 😉
I hope you enjoyed the talk, if it sounds like F# doesn’t apply to your line of work and never will – no hard feelings. If it does, then I encourage you to download the latest F# CTP and experiment.
[Ed. Hopefully I’ve been able to capture the essence of my presentation. While you can’t summarize everything about F# in a single blog post, hopefully this helps clarify some domains where we expect F# to be the most heavily used. If you have any questions please feel free to use the contact link on this blog.]