14 excellent reasons to use F#

F# makes it easy to write concise code to solve complex problems on all the major desktop and mobile platforms, primarily using functional programming.

Why F#?
Why F#?

F# is a strongly typed, functional-first programming language that lets you solve complex problems by writing simple code. Based on ML and built on the .Net framework, F# offers good interoperability, portability, and run-time speed as well as the "Five Cs" -- conciseness, convenience, correctness, concurrency, and completeness.

F# was initially available only on Windows as a Microsoft Research project, but it's now a first-class language on a number of platforms. You can use F# on Mac OS X and Linux with tool support in Xamarin Studio, MonoDevelop, Emacs, and others; on Windows with Visual Studio, Xamarin Studio, and Emacs; and on Android, iOS, and the Web using HTML5. In addition to general purpose programming, F# is applicable to GPU code, big data, games, and much more. 

F# is interactive
F# is interactive

One of the advantages of F# is that it has an interactive REPL (read, evaluate, print, loop) where you can try out code. Clockwise from the top left, we are seeing F# Interactive windows from Visual Studio 2013 Update 2 running in Windows 8.1, from the TryFsharp online editor running in Chrome, and from Xamarin Studio running on Mac OS X 10.9.3. The ;; tells F# Interactive to evaluate what you've typed; on TryFsharp.org the "run" button sends the same signal. Using a REPL to compile and test code before it goes into a full program both speeds up development and reduces bugs.

F# is for scripting
F# is for scripting

F# can be used as a scripting language as well as a programming language. Here we see a Visual Studio sample in which an F# script loads four F# program files and opens two .Net libraries before executing its own code. The notation [|…|] used here declares an array. The notation |> is a forward pipe, which passes the result of the left side to the function on the right side. The new lines here are not syntactically significant. They just make the code easier to read than having entire pipe expressions on a single line. 

F# is functional
F# is functional

F# supports functional programming constructs, such as treating functions as values, using unnamed functions in expressions, composition of functions to form new functions, curried functions, and the implicit definition of functions by way of the partial application of function arguments. In the upper screenshot, we define and use an add function. The body of the function is indented (like Python), and the argument types are inferred as integers because of the + operator. In the lower screenshot, we supply a type annotation after the argument name using a colon and a type name, so F# knows that phrase is a string type.

F# is concise
F# is concise

The code at left is a Quicksort-like algorithm implemented in F# (by Scott Wlaschin). The rec keyword indicates that the function is recursive. The match..with syntax is a switch statement on steroids, with | indicating cases. The [] indicates an empty list. The firstElem and otherElements are created automatically. 

Note that there are no type declarations mentioned anywhere in the code, meaning that the function can sort lists containing any type that supports comparison operators. The fun keyword is for defining an anonymous lambda function. 

For comparison, see the traditional C# implementation in the next slide.

C# implementation for comparison
C# implementation for comparison

You'll notice how much extra cruft the C# code has compared to the F# code. 

F# is really concise
F# is really concise

According to Scott Wlaschin, this version of quicksort -- all four lines of it -- has the typical concise look of F# written by an experienced functional coder. Of course, he'd be the first to point out that it doesn't sort in place. It took me multiple readings to make sense of the code, but it was worth the time. 

Briefly, the first case returns an empty list if passed one, providing an exit criterion; the second case splits the list into the first element and the rest, assigning the sublist starting with the smaller value to smaller and the other sublist to larger. Within the concatenation of the sublists, the function recursively sorts the smaller and larger lists.

F# reduces bugs through strong typing
F# reduces bugs through strong typing

Unlike JavaScript, Ruby, and Python, F# is strongly typed, not dynamically typed. Unlike C and C++, which are also strongly typed but require all types to be declared, F# performs type inference whenever possible. When type inference is not possible but the type needs to be known, the F# compiler will throw an error and suggest that you supply a type annotation, as we had to do in an earlier example for the (phrase:string) argument to the toHackerTalk function. Catching a type mismatch at compile time eliminates a whole class of run-time errors to which dynamically typed languages are prone. 

By the way, F# let bindings are immutable unless you specifically declare them mutable.

F# has rich List, String, and Array modules
F# has rich List, String, and Array modules

F# has a large, well-chosen set of objects including List, String, and Array modules based on the .Net framework. In this respect, it is also an object-oriented language, even though it is first and foremost a functional language. Notice that it doesn’t matter whether you use the module name or a typed variable name -- when you add the dot, the member functions will pop up. Some people argue that explicitly using the module name is a better style for a functional language than dotted variables, but I don't completely buy that argument.

F# is useful for MapReduce
F# is useful for MapReduce

MapReduce is an efficient two-step process often used on big data, and it's explicitly supported in Hadoop. In this F# example, we are mapping and reducing a list of integers. First we filter the list to the even numbers, then we double each number, and finally we take the sum of all the elements in the list to aggregate or reduce the result. List.map is a powerful higher-order function, which means it takes another function as an argument. In addition to lists and arrays, F# 3.1 supports records, sequences, data type providers, and LINQ (language-integrated query).

F# has records
F# has records

F# records represent simple aggregates of named values, optionally with members. In the example at left, first we define a Book record type with four named values, and then we create a record using the same four names. The F# compiler correctly infers the Book type by matching the names.

F# records can have optional values
F# records can have optional values

Records don't always have to include all of their named values. If you give a named value the option attribute when you define the type, then it can be left out of a record. When you set an optional value, it can either be None, which winds up as a null, or it can be Some followed by the value you want to set. Record fields differ from classes in that they are automatically exposed as properties. Classes and structures in F# are .Net classes and structures, compatible with C# and Visual Basic .Net, so I'll forgo examples.

F# has sequences
F# has sequences

A sequence in F# is a logical series of elements all of one type. Sequences are particularly useful when you have a large, ordered collection of data but do not necessarily expect to use all the elements. Individual sequence elements are computed only as required, so a sequence can provide better performance than a list in situations in which not all of the elements are used. The Seq module provides support for manipulations involving sequences. In the image at left, we demonstrate simple sequences, sequences with expressions, and sequences with filters.

F# supports data providers and LINQ
F# supports data providers and LINQ

Here we are using the TryFsharp online editor to open an online Freebase meteorology data set and query the data provider for cyclones that have recorded the highest wind values. The query { } syntax implements LINQ for F#. Use of this DLL is specific to TryFsharp.org. In Visual Studio 2013, you would open Microsoft.FSharp.Data.TypeProviders and then use the appropriate data provider service. The result: 

[Hurricane Andrew; Hurricane Hugo; 1900 Galveston hurricane;
  Tropical Storm Allison; Cyclone Tracy; Hurricane Iniki; Hurricane Ivan;
  1999 Odisha cyclone; Hurricane Katrina; Typhoon Talim; Hurricane Rita;
  Typhoon Herb; Hurricane Wilma; Typhoon Vera; 1962 Pacific typhoon season;
  Typhoon Ike; Typhoon Mireille; Typhoon Babe; Tropical Storm Arlene;
  Hurricane Irene; Typhoon Zeb; Typhoon Maemi; Typhoon Bess; Typhoon Chanchu;
  Typhoon Patsy; Typhoon Ewiniar; Hurricane Ioke; Typhoon Xangsane;…

F# can analyze Hadoop data
F# can analyze Hadoop data

In this example, we use the TryFsharp editor to open a Hadoop Hive instance that contains, among other data sets, measurements of iris flower features, along with units of measure annotations. Accordingly, we've enabled the use of unit annotations in the properties of the HiveTypeProvider. This calculation returns:

val avgPetalLength : float<Data.UnitSystems.SI.UnitNames.metre> = 0.0374966443

F# does pattern matching
F# does pattern matching

The F# matchexpression provides branching control that is based on the comparison of an expression with a set of patterns. Lines 1-7 of the example at left define a recursive isPalindromefunction. Lines 8-10 define a wrapper function for isPalindromethat calls it the first time using the entire string. Because "aba" is a palindrome, the thenclause of line 9 fires and returns Some s, and the matchstatement in line 11 generates "The string aba is palindrome".  The _ pattern in line 14 is the default case. 

The match..| statement in F# has many benefits over the switch..case statement in C#, C++, and Java, the most important of which is that it causes fewer bugs.

F# supports asynchronous workflows
F# supports asynchronous workflows

F# has its own syntax for asynchronous workflows. The async { expression } syntax defines a non-blocking computation. The do! keyword performs an asynchronous operation and waits for the result. The let! keyword waits on an asynchronous operation and assigns the result. And use! waits on an asynchronous operation, assigns the result, and releases the resource. Async.RunSynchronously executes an asynchronous operation and waits for its result. To add parallelism, use the Async.Parallel function, which takes a list of the Async objects, sets up the code for each Async task to run in parallel, and returns an Async object that represents the parallel computation. Then pipe that result to Async.RunSynchronously. (Example at left is from F# for Fun and Profit.)