Welcome to MSDN Blogs Sign in | Join | Help

F# in 20 Minutes - Part I

With the April Refresh hot off the presses, I figured it was time to write a concise, 20-minute introduction to F#. The goal isn't to teach F#, but rather give a quick overview of the language and some of the things you can do with it. I’ll divide the 20 minutes into three parts:

  • Part I - A slow introduction to F#, explaining your first program
  • Part II – A brisk overview of the foundational types and concepts in F#
  • Part III – A quick sampling into advanced topics

So if you're interested in seeing what the fuss is all about, the read on.

What is F# and why should I learn it?

F# is a functional programming language built on .NET. Just like C# and VB.NET, F# can take advantage of core libraries such as Windows Presentation Foundation, Windows Communication Foundation, Visual Studio Tools for Office, etc. With F# you can even write XBox games using XNA.

But just because you can write code in a new language doesn't mean you should. So why use F#? Because being a functional language, F# makes writing some classes of programs much easier than its imperative cousins like C#. Parallel Programming and Language-Oriented Programming are two such domains that can be expressed easily in F#.

If you’ve ever written a .NET application and found yourself fighting against with the language to get your idea expressed, then perhaps F# is what you’ve been looking for.

Getting Started

To get started with F# download and install the latest release (v1.9.4.15) at:
http://research.microsoft.com/research/downloads/Details/7ac148a7-149b-4056-aa06-1e6754efd36f/Details.aspx?0sr=d

(In a day or two it will be on the main site http://research.microsoft.com/fsharp/release.aspx)

 

This will install the F# Project System on top of Visual Studio 2005 and 2008. First, create a new F# Project.

clip_image001

Next, add a new F# Source File. By default it will add a lot of ‘tutorial’ code, delete all that and insert the following into the empty code editor:

#light

let square x = x * x

let numbers = [1 .. 10]

let squares = List.map square numbers

printfn "N^2 = %A"squares

open System
Console.ReadKey(true)

Press F5 to run your program, and you'll see the following:

clip_image002

Nothing terribly exciting yet. Let’s will break the code down the code line by line and then see if what’s really going on, but before we do that, let me introduce VFSI.

F# Interactive for Visual Studio

The F# Interactive Console (FSI) is what’s know as a ' REPL loop’ for Read-Evaluate-Print-Loop. This means: taking a code snippet, compiling and executing it, then printing the results. With it you can rapidly prototype and test your programs. To enable FSI from within Visual Studio (which is called VFSI), open up the Add-in Manager on the Tools menu item.

clip_image003

And check "F# Interactive for Visual Studio". Next, highlight the first two lines of the program...

clip_image004

... and then press ALT+Enter. (Actually, you'll need to press ALT+Enter twice if FSI isn't opened already.) You should see a tool window appear with the text:

image

What you just did was send the code snippet directly to the F# Interactive session, and the results were displayed to the output. The result was the definition of a function 'square' which takes a type 'int' and returns a type 'int'.

Next try typing "List.map square [1 .. 2 .. 10];;" into the FSI window. The ';;' indicates to FSI to stop reading in program text and evaluate the result.

> List.map square [1 .. 2 .. 10];;
val it : int list = [1; 9; 25; 49; 81]

 

Now we have the ability to easily explore the F# language via FSI, let's go into what that code actually means. I recommend however that you type code inside the Visual Studio code editor and use 'Highlight + ALT + Enter' to send the code to FSI. Otherwise, you will have to retype your code very time you have a typeo. (Which, at least for me, is very often.)

Language Basics

#light (OCaml compat)

F# has its roots in a programming language called OCaml and has the ability to cross compile OCaml code, meaning that it can compile simple OCaml programs unmodified. This ability however, means that F# requires some unsavory syntax by default. #light (pronounced hash-light) is a compiler directive that simplifies the syntax of the language.

I highly recommend that you keep #light on since most F# code snippets you find will either declare it, or assume that it has been declared.

let square x = x * x (Type Inference)

This defines a function called 'square' which squares a number x. Consider for a moment the equivalent C# code:

public static int square(int x)
{
    return x * x;
}

Whereas C# requires you to specify type information as well as what the function actually returns, the F# compiler simply figures it out for you. This is referred to as type inference.

From the function signature F# knows that square takes a single parameter named 'x' and that the function would return 'x * x'. (That last thing evaluated in a function body is the ‘return value’, so no need for a ‘return’ keyword.) Since many primitive types support (*) such as byte, uint64, double, etc. F# defaults to int, a signed 32-bit integer.

Now consider the following code which provides a 'type annotation' for one of the parameters, that is telling the compiler the type to expect. Since x is stated to be of type 'string', and (+) is only defined for taking two strings, then the parameter y must also be a string. And the result of x + y is the concatenation of both strings.

> let concat (x : string) y = x + y;;
val concat : string -> string -> string

> concat "Hello, " "World!";;
val it : string = "Hello, World!"

We'll cover more advanced topics in type inference later. But for now just enjoy the fact that the F# compiler has the smarts to figure out what you mean, and doesn't require any hand holding.

let numbers = [1 .. 10] (F# Lists)

The next line simply declares a list of numbers one through ten. If you had typed [|1 .. 10|] that would have created a .NET array of integers. But an F# list is an immutable linked list, which is the backbone of functional programming. Try typing these things into the FSI window (remember to add a ‘;;’ at the end of each line):

// Define a list 
let vowels = ['e'; 'i'; 'o'; 'u'] 

// Attach item to front (cons)
let cons = 'a' :: vowels 

// Concat two lists
let sometimes = vowels @ ['y']

I’ll cover lists more in-depth in Part II.

let squares = List.map square numbers (List.map and first-order functions)

Now we have a list of integers ('numbers') and a function ('square'), we want to create a new list where each item is the result of calling our function. In other words, mapping our function to each item in the list.

Fortunately, List.map does just that. Consider another example:

> List.map (fun x -> x % 2 = 0) [1 .. 10];;
val it : bool list
= [false; true; false; true; false; true; false; true; false; true]

The code (fun i -> i % 2 = 0) defines an anonymous function, called a lambda expression, that has a parameter x and the function returns the result of "x % 2 = 0", which is whether or not x is even.

Now notice what we just did - we passed a function as a parameter to another function. You simply can't do that in C#. (At least not easily.) But in F# it allowed us to be very expressive and succinct in our code. Passing around functions as values is known as 'first order functions' and is a hallmark of functional programming.

printfn "N^2 = %A" squares

printf is a simple and type-safe way to print text to the console window. To get a better feel for how printf works consider this example which prints an integer, floating-point number, and a string:

> printfn "%d * %f = %s" 5 0.75 ((5.0 * 0.75).ToString());;
5 * 0.750000 = 3.75
val it : unit = ()

The %d, %f, and %s are holes for integers, floats, strings. %A may also be used to print anything else.

Console.ReadKey(true) (.NET Interop)

The last line in our program was simply a call to System.Console.ReadKey, in order to pause the program before it closed. Since F# is built on top of .Net you can call any .NET library from F# - from Regular Expressions to WinForms. The line ‘open System’ simply opened the namespace and brought its types into scope, similar to the using keyword of C#.

Now that we have the absolute basics out of the way, we can move onto the more interesting foundational types and concepts of F# so stay tuned for Part II!

Published Friday, May 02, 2008 6:53 PM by ChrSmith
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Saturday, May 03, 2008 4:25 AM by chris core

# chris core

Saturday, May 03, 2008 4:23 PM by R

# re: F# in 20 Minutes - Part I

Interesting posting!

It seems to require the full version of VS, though. How would one go about using it with free Express editions?

Saturday, May 03, 2008 4:31 PM by Don Syme's WebLog on F# and Other Research Projects

# Learning F#: Some great blog posts from the F# team

Brian and Chris have been writing some great blog posts of late on learning F#. I can highly recommend

Saturday, May 03, 2008 6:45 PM by secretGeek

# re: F# in 20 Minutes - Part I

Great introduction Chris!

@R, re: "require the full version of VS..?"

If you don't have Visual Studio, then you can run F Sharp Interactive as a console application (instead of a visual studio window).

The compiler and tools don't require Visual Studio -- they just offer Visual Studio integration as a "value add" feature.

Visual Studio express prohibits add-ons, so that kind of kills its ability to benefit from FSI. (Don Syme wrote answered a question about that here: http://cs.hubfs.net/forums/thread/3434.aspx )

Sunday, May 04, 2008 5:50 AM by Peter Gum

# re: F# in 20 Minutes - Part I

Terrific! Just the right level of explanation that I badly need. Keep it up.

Sunday, May 04, 2008 6:33 AM by Jan Midtgaard

# re: F# in 20 Minutes - Part I

"Passing around functions as values is known as 'first order functions' and is a hallmark of functional programming."

No, it's called 'first-class functions' (because functions are first-class citizens, like, e.g., numbers) or 'higher-order functions' -- not 'first-order functions'. Languages with 'first-order functions' don't pass them around.

Sunday, May 04, 2008 6:57 PM by James Hurst

# re: F# in 20 Minutes - Part I

I appreciate your article, and just want to point out a couple of items that could perhaps be improved. For beginner's tutorials, little syntax errors can be confusing.

1. Under "printfn "N^2 = %A" squares", do you mean to say "printf is a simpler.." or "printfn is a simpler"? These look like two distinct things to me (I'm a noob obviously).

2. Under "let numbers = [1..10]", how're we supposed to type these lines into the FSI window? Exactly as is? Nothing happens. Do you intend for us to use the ";;" syntax to cause the line to execute? That yields an error. You might want to be a bit more explicit yet at this point to avoid frustrating your readers.

3. Under the picture of the FSI window, where you instruct your user to type "[1 .. 2 .. 10]" - an explanation of what the heck that IS, would be helpful here!

4. I'm guessing that "FSI" means "F Sharp Interactive" - but perhaps you could say that explicitly?

5. Where you give instructions on how to use the Add-in Manager to add the FSI window, you could stand to be a bit more explicit (IMO). You leave us with that Add-in Manager still open! What about those other two checkboxes - "Startup" and "Command Line"? Do you intend for us to click "OK" here before continuing on to your next step?

6. You skip a few beats in instructing your readers in creating their first F# project. "Add a new F# Source File"? Don't you need to let them know that they first need to create a project? And what about all that code and comments that come pre-loaded within that new F# source file I created? What's up with that? Do we need to delete it all first?

Monday, May 05, 2008 4:27 PM by Jonathan Pryor

# re: F# in 20 Minutes - Part I

Minor quibble:

> Now notice what we just did - we passed a function as a parameter to another function. You simply can't do that in C#. (At least not easily.)

For C# we can make the distinction between definition and use.  Definition is more verbose, due to the need for types, but it's not impossible either -- you simply use a Delegate type:

class List {

 public static TOutput[] map<TInput, TOutput> (Func<Tnput, TOutput> f, TInput[] input) {...}

}

Usage would actually be similarly verbose to F#:

var squares = List.map (square, numbers);

List.map (x => x % 2 == 0, new int[]{1, /* ... */ 10});

The overhead here is the array creation, not the lambda expression.

(And in this case, using System.Array.Convert() would make more sense than defining a new List.map method.)

Monday, May 05, 2008 10:54 PM by ChrSmith

# re: F# in 20 Minutes - Part I

Thanks for the feedback, I'll update this post to (hopefully) clarify things more.

And if I need to remember to write out:

public static TOutput[] map<TInput, TOutput> (Func<Tnput, TOutput> f, TInput[] input) {...}

every time I pass declare method which takes a function as a parameter, I consider that hard to do. Even if the call-site code is clean ;)

Thanks,

-Chris

Tuesday, May 06, 2008 8:54 AM by IanS

# re: F# in 20 Minutes - Part I

@R, re: "require the full version of VS..?"

You can use F# with the free Visual Studio 2008 Shell. See the following for more info:

http://11011.net/archives/000721.html

http://fsharpnews.blogspot.com/2007/12/f-in-visual-studio-for-free.html

Tuesday, May 06, 2008 10:31 AM by Eric Eilebrecht

# re: F# in 20 Minutes - Part I

Great article; looking forward to the rest of the series.  I've been meaning to look at F#, and this looks like a great quick intro.

On the comparison to C#, I'd like to echo the previous comment that it's actually quite easy to pass a function to a function.  And, in fact, the System.Linq namespace already defines an equivalent of "map."  Your full example looks something like this in C#:

using System;

using System.Linq;

class Program

{

   static void Main()

   {

       Func<int, int> square = x => x * x;

       int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

       var squares = numbers.Select(square);

       Console.WriteLine("N^2 = {0}", squares.Aggregate("", (s, i) => s + " " + i));

       Console.ReadKey(true);

   }

}

Note that the hard part is declaring the sequence (which of course would be easier if there was an "Enumerable.Sequence" method or somesuch), and formatting the output.

Another approach, more in the spirit of the latest wave of C# features, would be:

   static IEnumerable<int> Sequence(int start, int end)

   {

       for (int i = start; i < end; i++)

           yield return i;

   }

   static void Main()

   {

       var squares = from x in Sequence(1, 10) select x * x;

       Console.WriteLine("N^2 = {0}", squares.Aggregate("", (s, i) => s + " " + i));

       Console.ReadKey(true);

   }

And it's not true that declaring a function that takes a function arg is necessarily as verbose as declaring "map" is; that example is complicated by the fact that "map" has to be generic.  I wonder what the declaration of "map" looks like in F#?  Don't you have to do something special to keep the compiler from assuming all the types are "int," like it did for your "square" function?

Love the interactive evaluation thing.  That might make me pick up F# all by itself.

Thanks again for the article!

Friday, May 09, 2008 6:21 PM by Chris Smith's completely unique view

# F# in 20 Minutes – Part II

Now that we have covered the basics, in minutes 8 - 14 we will cover the foundational concepts and types

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker