Chapter 1. Introduction to F#

F# is a powerful language that spans multiple paradigms of development. This chapter provides a brief introduction to the heart of F#—the F# compiler, tools, and its place in Visual Studio 11.

In this chapter, you will create a couple of simple F# applications, and then I’ll point out key Visual Studio features for F# development. I won’t cover much of Visual Studio here, so I encourage you to explore the IDE on your own.

If you are already familiar with Visual Studio, you should still skim through this chapter. Creating and debugging F# projects works just like C# or VB.NET; however, F# has a unique characteristic when it comes to multiple-file projects. In addition, F# has a feature called F# Interactive that will dramatically increase your productivity. Not to be missed!

Getting to Know F#

As with all programming books, it is customary to write a Hello, World application, and I don’t want to deviate from tradition. Open up Notepad or your favorite text editor and create a new file named HelloWorld.fs with the following text:

// HelloWorld.fs

printfn "Hello, World",

Success! You’ve just written your first F# program. To compile this application, use the F# compiler, fsc.exe, located in the Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0 folder. (Don’t worry, you won’t have to remember that.)

The following snippet shows calling the F# compiler on the command line to build and run your application:

C:\Programming F# Source\Ch01>fsc HelloWorld.fs
Microsoft (R) F# 3.0 Compiler build 11.0.50522.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

C:\Programming F# Source\Ch01>HelloWorld.exe
Hello, World!

Visual Studio 11

Tools are the lifeblood of any programming language, and F# is no different. Although you can successfully write F# code in your favorite text editor and invoke the compiler from the command line, you’ll likely be more productive using tools. Like C# and VB.NET, F# is a first-class citizen in Visual Studio, with all the features that you might expect, including debugger support, IntelliSense, project templates, and so on.

Note

Alternatively, you can try F# out in your browser.

Let’s revisit our Hello, World application, but this time using Visual Studio.

To create your first F# project, open up the Visual Studio IDE and select FileNew Project from the menu bar to open the New Project dialog, which is shown in Figure 1-1. Select Visual F# in the left pane, select F# Application in the right pane, and then click OK.

Select F# Application to start your first F# project
Figure 1-1. Select F# Application to start your first F# project

After you click OK in the New Project dialog, you’ll see an empty code editor—a blank canvas ready for you to create your F# masterpiece. Next, type the following code into the F# editor:

printfn "Hello, World"

Now press Ctrl-F5 to run your application. When your application starts, a console window will appear and display the entirely unsurprising result shown in Figure 1-2.

Hello World in F#
Figure 1-2. Hello World in F#

Your Second F# Program

It may be startling to see a program work without an explicit Main method. You will see why this is admissible in Chapter 2, but for now, let’s create a more meaningful Hello, World–type program to get a feel for basic F# syntax.

The code in Example 1-1 will create a program that accepts two command-line parameters and prints them to the console. In addition, it displays the current time.

Example 1-1. Mega Hello World
// Mega Hello World
//
// Take two command-line parameters and then print
// them along with the current time to the console.

open System

[<EntryPoint>]
let main (args : string[]) =

    if args.Length <> 2 then
        failwith "Error: Expected arguments <greeting> and <thing>"

    let greeting, thing = args.[0], args.[1]
    let timeOfDay = DateTime.Now.ToString("hh:mm tt")

    printfn "%s, %s at %s" greeting thing timeOfDay

    // Program exit code
    0

Hopefully you are curious about what is going on. Let’s look at this program line by line to see how it works.

Values

Example 1-1 introduces three values named greeting, thing, and timeOfDay:

    let greeting, thing = args.[0], args.[1]
    let timeOfDay = DateTime.Now.ToString("hh:mm tt")

The key thing here is that the let keyword binds a name to a value. It is worth pointing out that unlike most other programming languages, values in F# are immutable by default, meaning they cannot be changed once initialized. We will cover why values are immutable in Chapter 3, but for now it is sufficient to say it has to do with “functional programming.”

F# is also case sensitive, so any two values with names that only differ by case are considered different:

let number = 1
let Number = 2
let NUMBER = 3

A value’s name can be any combination of letters, numbers, underscores (_), and apostrophes ('). However, the name must begin with a letter or an underscore.

Note

You can enclose the value’s name with a pair of tick marks, in which case the name can contain any character except for tabs and new lines. This allows you to refer to values and functions exposed from other .NET languages that may conflict with F# keywords:

let ``this.Isn't %A% good value Name$!@#`` = 5

Whitespace Matters

Other languages (e.g., C#) use semicolons and curly braces to indicate when statements and blocks of code are complete. However, programmers typically indent their code to make it more readable anyway, so these extra symbols often just add syntactic clutter.

In F#, whitespace—spaces and newlines—is significant. The F# compiler allows you to use whitespace to delimit code blocks. For example, anything indented more than the if keyword is considered to be in the body of the if statement. Because tab characters can indicate an unknown number of space characters, they are prohibited in F# code.

Note

You can configure the Visual Studio editor to automatically convert tab characters into spaces by changing the relevant setting under ToolsOptionsText EditorF#.

Reviewing Example 1-1, notice that the body of the main method was indented by four spaces, and the body of the if statement was indented by another four spaces:

let main (args : string[]) =

    if args.Length <> 2 then
        failwith "Error: Expected arguments <greeting> and <thing>"

    let greeting, thing = args.[0], args.[1]
    let timeOfDay = DateTime.Now.ToString("hh:mm tt")

    printfn "%s, %s at %s" greeting thing timeOfDay

    // Program exit code
    0

If the body of the if statement, the failwith "..." expression, was dedented four spaces and therefore lined up with the if keyword, the F# compiler would produce a warning. This is because the compiler wouldn’t be able to determine whether the failwith was meant for the body of the if statement or the main function:

[<EntryPoint>]
let main (args : string[]) =

    if args.Length <> 2 then
    failwith "Error: Expected arguments <greeting> and <thing>"

Warning FS0058: Possible incorrect indentation: this token is offside of
context started at position (25:5). Try indenting this token further or
using standard formatting conventions.

The general rule is that anything belonging to a method or statement must be indented farther than the keyword that began the method or statement. So in Example 1-1, everything in the main method was indented past the first let and everything in the if statement was indented past the if keyword. As you see and write more F# code, you will quickly find that omitting semicolons and curly braces makes the code easier to write and much easier to read.

.NET Interop

Example 1-1 also demonstrates how F# can interoperate with existing .NET libraries:

open System

// ...

let timeOfDay = DateTime.Now.ToString("hh:mm tt")

This example shows the DateTime.Now property from the System namespace in the mscorlib.dll assembly in use.

The .NET Framework contains a broad array of libraries for everything from graphics to databases to web services. F# can take advantage of any .NET library natively by calling directly into it. Conversely, any code written in F# can be consumed by other .NET languages. This also means that F# applications can run on any platform that supports .NET. So the F# programs you write can run on phones, tablets, PCs, and so on.

Note

For more information on .NET libraries, see Appendix A for a quick tour of what’s available. For more information about F# interoperating with other .NET languages, refer to Appendix B.

Comments

F# allows you to comment your code. To declare a single-line comment, use two slashes (//); everything after them until the end of the line will be ignored by the compiler:

    // Program exit code   

For larger comments, you can use (* and *). Everything between the two tokens will be ignored:

(*
Comment
spanning
multiple
lines
*)

For F# applications written in Visual Studio, there is a third type of comment—an XML documentation comment. If a comment starting with three slashes, ///, is placed above an identifier, Visual Studio will display the comment’s text when you hover the mouse over the identifier.

Figure 1-3 shows applying an XML documentation comment and its associated tooltip.

XML documentation comments
Figure 1-3. XML documentation comments

F# Interactive

So far you have written some F# code and executed it, and the rest of the book will have many more examples. Although you could leave a wake of new projects to test out code, Visual Studio comes with a tool called F# Interactive or FSI. The FSI window will not only make it much easier to work through the examples in this book, but it will also help you write applications.

F# Interactive is a tool known as a REPL, which stands for read, evaluate, print, loop. It accepts F# code, compiles and executes it, then prints the results. This allows you to quickly and easily experiment with F# without needing to create new projects or build a full application to test the results of a code snippet.

Most Visual Studio configurations launch the F# Interactive window with the Ctrl-Alt-F keyboard combination. Once the FSI window is available, it accepts F# code until you terminate the input with ;; and a newline. The code entered is compiled and executed as shown in Figure 1-4.

The FSI window prints any new values introduced as well as their types. Figure 1-4 shows val x : int = 42, declaring that a value x of type int was created with value 42. If the FSI window evaluates an expression that was not assigned to a value, it will instead assign it to the name it.

The F# Interactive window
Figure 1-4. The F# Interactive window

As the F# compiler processes FSI input, it will display the name, type, and value of identifiers. For example, in Figure 1-4 the value x was introduced with type int and value 42.

Note

If you are running F# without Visual Studio, you can find the console version of F# Interactive in the same directory you found fsc.exe with the name fsi.exe.

Try running these other snippets in FSI. Remember that every code snippet is terminated with a ;;:

> 2 + 2;;
val it : int = 4
> // Introduce two values
let x = 1
let y = 2.3;;

val x : int = 1
val y : float = 2.3

> float x + y;;
val it : float = 3.3
> let cube x = x * x * x;;

val cube : int -> int

> cube 4;;
val it : int = 64

FSI can dramatically simplify testing and debugging your applications because you can send F# code from your current project to the FSI window by highlighting it and pressing Alt-Enter.

After selecting all the code in Example 1-1 within the code editor and pressing Alt-Enter, you will see the following in the FSI window:

>

val main : string [] -> int

This allows you to write code in the Visual Studio editor—which offers syntax highlighting and IntelliSense—but test your code using the FSI window. You can check the main method’s implementation by calling it from FSI:

> main [| "Hello"; "World" |];;
Hello, World at 10:52 AM
val it : int = 0

Note

The majority of the examples in this book are taken directly from FSI sessions. I encourage you to use FSI to follow along and experiment with the F# language’s syntax.

You can find a copy of the source code for all examples in the book on GitHub.

Managing F# Source Files

When you are starting out with F# programming, most of the programs you write will live only in FSI or perhaps in a single code file. Your F# projects, however, will quickly grow and be broken up across multiple files and eventually multiple projects.

The F# language has some unique characteristics when it comes to managing projects with multiple source files. In F#, the order in which code files are compiled is significant.

You can only call into functions and classes defined earlier in the code file or in a separate code file compiled before the file where the function or class is used. If you rearrange the order of the source files, your program may no longer build!

Note

The reason for this significance in compilation order is type inference, a topic covered in Chapter 2.

F# source files are compiled from top to bottom in the order they are displayed in Visual Studio’s Solution Explorer. Whenever you add a new code file it is added at the bottom of the list, but if you want to rearrange the source files, you can right click a code file and select “Move Up” or “Move Down,” as seen in Figure 1-5. The keyboard shortcut for reordering project files is Alt-Up and Alt-Down.

Reordering files within an F# project
Figure 1-5. Reordering files within an F# project

Warning

A feature sorely missing from Visual Studio is the ability to organize an F# project’s source code files into subfolders. Although not exposed by the Visual Studio UI, you can edit the project file directly to achieve this. Many of the in-depth examples of this book utilize this technique

Now that you are armed with the logistical know-how for creating, compiling, and testing F# applications, the rest of this book will focuses exclusively on the syntax and semantics of the F# programming language.

In just a few chapters, you’ll master the syntax of the F# language and be able to apply it across several programming paradigms. Good luck and have fun!

Get Programming F# 3.0, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.