This cheatsheet glances over some of the common syntax of F# 3.0. If you have any comments, corrections, or suggested additions, please open an issue or send a pull request to https://github.com/dungpa/fsharp-cheatsheet.

Comments

Block comments are placed between (* and *) . Line comments start from // and continue until the end of the line.

(* This is block comment *) // And this is line comment

XML doc comments come after /// allowing us to use XML tags to generate documentation.

/// The `let` keyword defines an (immutable) value let result = 1 + 1 = 2

Strings

F# string type is an alias for System.String type.

/// Create a string using string concatenation let hello = "Hello" + " World"

Use verbatim strings preceded by @ symbol to avoid escaping control characters (except escaping " by "" ).

let verbatimXml = @"<book title=""Paradise Lost"">"

We don't even have to escape " with triple-quoted strings.

let tripleXml = """<book title="Paradise Lost">"""

Backslash strings indent string contents by stripping leading spaces.

let poem = "The lesser world was daubed

\ By a colorist of modest skill

\ A master limned you in the finest inks

\ And with a fresh-cut quill."

Basic Types and Literals

Most numeric types have associated suffixes, e.g., uy for unsigned 8-bit integers and L for signed 64-bit integer.

let b , i , l = 86uy , 86 , 86L val b : byte = 86uy val i : int = 86 val l : int64 = 86L

Other common examples are F or f for 32-bit floating-point numbers, M or m for decimals, and I for big integers.

let s , f , d , bi = 4.14F , 4.14 , 0.7833M , 9999I val s : float32 = 4.14f val f : float = 4.14 val d : decimal = 0.7833M val bi : System.Numerics.BigInteger = 9999

See Literals (MSDN) for complete reference.

Functions

The let keyword also defines named functions.

let negate x = x * - 1 let square x = x * x let print x = printfn "The number is: %d " x let squareNegateThenPrint x = print ( negate ( square x ))

Pipe and composition operators

Pipe operator |> is used to chain functions and arguments together. Double-backtick identifiers are handy to improve readability especially in unit testing:

let ``square, negate, then print`` x = x |> square |> negate |> print

This operator is essential in assisting the F# type checker by providing type information before use:

let sumOfLengths ( xs : string []) = xs |> Array . map ( fun s -> s . Length ) |> Array . sum

Composition operator >> is used to compose functions:

let squareNegateThenPrint' = square > > negate > > print

Recursive functions

The rec keyword is used together with the let keyword to define a recursive function:

let rec fact x = if x < 1 then 1 else x * fact ( x - 1 )

Mutually recursive functions (those functions which call each other) are indicated by and keyword:

let rec even x = if x = 0 then true else odd ( x - 1 ) and odd x = if x = 1 then true else even ( x - 1 )

Pattern Matching

Pattern matching is often facilitated through match keyword.

let rec fib n = match n with | 0 -> 0 | 1 -> 1 | _ -> fib ( n - 1 ) + fib ( n - 2 )

In order to match sophisticated inputs, one can use when to create filters or guards on patterns:

let sign x = match x with | 0 -> 0 | x when x < 0 -> - 1 | x -> 1

Pattern matching can be done directly on arguments:

let fst' ( x , _) = x

or implicitly via function keyword:

/// Similar to `fib`; using `function` for pattern matching let rec fib' = function | 0 -> 0 | 1 -> 1 | n -> fib' ( n - 1 ) + fib' ( n - 2 )

For more complete reference visit Pattern Matching (MSDN).

Collections

Lists

A list is an immutable collection of elements of the same type.

// Lists use square brackets and `;` delimiter let list1 = [ "a" ; "b" ] // :: is prepending let list2 = "c" :: list1 // @ is concat let list3 = list1 @ list2 // Recursion on list using (::) operator let rec sum list = match list with | [] -> 0 | x :: xs -> x + sum xs

Arrays

Arrays are fixed-size, zero-based, mutable collections of consecutive data elements.

// Arrays use square brackets with bar let array1 = [| "a" ; "b" |] // Indexed access using dot let first = array1 . [ 0 ]

Sequences

A sequence is a logical series of elements of the same type. Individual sequence elements are computed only as required, so a sequence can provide better performance than a list in situations in which not all the elements are used.

// Sequences can use yield and contain subsequences let seq1 = seq { // "yield" adds one element yield 1 yield 2 // "yield!" adds a whole subsequence yield! [ 5.. 10 ] }

Higher-order functions on collections

The same list [ 1; 3; 5; 7; 9 ] or array [| 1; 3; 5; 7; 9 |] can be generated in various ways.

Using range operator .. let xs = [ 1.. 2.. 9 ]

Using list or array comprehensions let ys = [| for i in 0.. 4 -> 2 * i + 1 |]

Using init function let zs = List . init 5 ( fun i -> 2 * i + 1 )

Lists and arrays have comprehensive sets of higher-order functions for manipulation.

fold starts from the left of the list (or array) and foldBack goes in the opposite direction let xs' = Array . fold ( fun str n -> sprintf " %s , %i " str n ) "" [| 0.. 9 |]

reduce doesn't require an initial accumulator let last xs = List . reduce ( fun acc x -> x ) xs

map transforms every element of the list (or array) let ys' = Array . map ( fun x -> x * x ) [| 0.. 9 |]

iter ate through a list and produce side effects let _ = List . iter ( printfn " %i " ) [ 0.. 9 ]

All these operations are also available for sequences. The added benefits of sequences are laziness and uniform treatment of all collections implementing IEnumerable<'T> .

let zs' = seq { for i in 0.. 9 do printfn "Adding %d " i yield i }

Tuples and Records

A tuple is a grouping of unnamed but ordered values, possibly of different types:

// Tuple construction let x = ( 1 , "Hello" ) // Triple let y = ( "one" , "two" , "three" ) // Tuple deconstruction / pattern let ( a' , b' ) = x

The first and second elements of a tuple can be obtained using fst , snd , or pattern matching:

let c' = fst ( 1 , 2 ) let d' = snd ( 1 , 2 ) let print' tuple = match tuple with | ( a , b ) -> printfn "Pair %A %A " a b

Records represent simple aggregates of named values, optionally with members:

// Declare a record type type Person = { Name : string ; Age : int } // Create a value via record expression let paul = { Name = "Paul" ; Age = 28 } // 'Copy and update' record expression let paulsTwin = { paul with Name = "Jim" }

Records can be augmented with properties and methods:

type Person with member x . Info = ( x . Name , x . Age )

Records are essentially sealed classes with extra topping: default immutability, structural equality, and pattern matching support.

let isPaul person = match person with | { Name = "Paul" } -> true | _ -> false

Discriminated Unions

Discriminated unions (DU) provide support for values that can be one of a number of named cases, each possibly with different values and types.

type Tree < ' T > = | Node of Tree < ' T > * ' T * Tree < ' T > | Leaf let rec depth = function | Node ( l , _, r ) -> 1 + max ( depth l ) ( depth r ) | Leaf -> 0

F# Core has a few built-in discriminated unions for error handling, e.g., Option and Choice.

let optionPatternMatch input = match input with | Some i -> printfn "input is an int= %d " i | None -> printfn "input is missing"

Single-case discriminated unions are often used to create type-safe abstractions with pattern matching support:

type OrderId = Order of string // Create a DU value let orderId = Order "12" // Use pattern matching to deconstruct single-case DU let ( Order id ) = orderId

Exceptions

The failwith function throws an exception of type Exception .

let divideFailwith x y = if y = 0 then failwith "Divisor cannot be zero." else x / y

Exception handling is done via try/with expressions.

let divide x y = try Some ( x / y ) with :? System . DivideByZeroException -> printfn "Division by zero!" None

The try/finally expression enables you to execute clean-up code even if a block of code throws an exception. Here's an example which also defines custom exceptions.

exception InnerError of string exception OuterError of string let handleErrors x y = try try if x = y then raise ( InnerError ( "inner" )) else raise ( OuterError ( "outer" )) with InnerError ( str ) -> printfn "Error1 %s " str finally printfn "Always print this."

Classes and Inheritance

This example is a basic class with (1) local let bindings, (2) properties, (3) methods, and (4) static members.

type Vector ( x : float , y : float ) = let mag = sqrt ( x * x + y * y ) // (1) member this . X = x // (2) member this . Y = y member this . Mag = mag member this . Scale ( s ) = // (3) Vector ( x * s , y * s ) static member ( + ) ( a : Vector , b : Vector ) = // (4) Vector ( a . X + b . X , a . Y + b . Y )

Call a base class from a derived one.

type Animal () = member __ . Rest () = () type Dog () = inherit Animal () member __ . Run () = base . Rest ()

Upcasting is denoted by :> operator.

let dog = Dog () let animal = dog :> Animal

Dynamic downcasting ( :?> ) might throw an InvalidCastException if the cast doesn't succeed at runtime.

let shouldBeADog = animal :?> Dog

Interfaces and Object Expressions

Declare IVector interface and implement it in Vector' .

type IVector = abstract Scale : float -> IVector type Vector' ( x , y ) = interface IVector with member __ . Scale ( s ) = Vector' ( x * s , y * s ) :> IVector member __ . X = x member __ . Y = y

Another way of implementing interfaces is to use object expressions.

type ICustomer = abstract Name : string abstract Age : int let createCustomer name age = { new ICustomer with member __ . Name = name member __ . Age = age }

Active Patterns

Complete active patterns:

let (| Even | Odd |) i = if i % 2 = 0 then Even else Odd let testNumber i = match i with | Even -> printfn " %d is even" i | Odd -> printfn " %d is odd" i

Parameterized active patterns:

let (| DivisibleBy |_|) by n = if n % by = 0 then Some DivisibleBy else None let fizzBuzz = function | DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz" | DivisibleBy 3 -> "Fizz" | DivisibleBy 5 -> "Buzz" | i -> string i

Partial active patterns share the syntax of parameterized patterns but their active recognizers accept only one argument.

Compiler Directives

Load another F# source file into FSI.

#load "../lib/StringParsing.fs"

Reference a .NET assembly ( / symbol is recommended for Mono compatibility).

#r "../lib/FSharp.Markdown.dll"

Include a directory in assembly search paths.

#I "../lib" #r "FSharp.Markdown.dll"

Other important directives are conditional execution in FSI ( INTERACTIVE ) and querying current directory ( __SOURCE_DIRECTORY__ ).

#if INTERACTIVE let path = __SOURCE_DIRECTORY__ + "../lib" #else let path = "../../../lib" #endif

val result : bool



Full name: fsharpcheatsheet.result





The `let` keyword defines an (immutable) value

val hello : string



Full name: fsharpcheatsheet.hello





Create a string using string concatenation

val verbatimXml : string



Full name: fsharpcheatsheet.verbatimXml

val tripleXml : string



Full name: fsharpcheatsheet.tripleXml

val poem : string



Full name: fsharpcheatsheet.poem

val b : byte



Full name: fsharpcheatsheet.b

val i : int



Full name: fsharpcheatsheet.i

val l : int64



Full name: fsharpcheatsheet.l

val s : float32



Full name: fsharpcheatsheet.s

val f : float



Full name: fsharpcheatsheet.f

val d : decimal



Full name: fsharpcheatsheet.d

val bi : System.Numerics.BigInteger



Full name: fsharpcheatsheet.bi

val negate : x:int -> int



Full name: fsharpcheatsheet.negate

val x : int

val square : x:int -> int



Full name: fsharpcheatsheet.square

val print : x:int -> unit



Full name: fsharpcheatsheet.print

val printfn : format:Printf.TextWriterFormat<'T> -> 'T



Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn

val squareNegateThenPrint : x:int -> unit



Full name: fsharpcheatsheet.squareNegateThenPrint

val ( square, negate, then print ) : x:int -> unit



Full name: fsharpcheatsheet.( square, negate, then print )

val sumOfLengths : xs:string [] -> int



Full name: fsharpcheatsheet.sumOfLengths

val xs : string []

Multiple items

val string : value:'T -> string



Full name: Microsoft.FSharp.Core.Operators.string



--------------------

type string = System.String



Full name: Microsoft.FSharp.Core.string

module Array



from Microsoft.FSharp.Collections

val map : mapping:('T -> 'U) -> array:'T [] -> 'U []



Full name: Microsoft.FSharp.Collections.Array.map

val s : string

property System.String.Length: int

val sum : array:'T [] -> 'T (requires member ( + ) and member get_Zero)



Full name: Microsoft.FSharp.Collections.Array.sum

val squareNegateThenPrint' : (int -> unit)



Full name: fsharpcheatsheet.squareNegateThenPrint'

val fact : x:int -> int



Full name: fsharpcheatsheet.fact

val even : x:int -> bool



Full name: fsharpcheatsheet.even

val odd : x:int -> bool



Full name: fsharpcheatsheet.odd

val fib : n:int -> int



Full name: fsharpcheatsheet.fib

val n : int

val sign : x:int -> int



Full name: fsharpcheatsheet.sign

val fst' : x:'a * 'b -> 'a



Full name: fsharpcheatsheet.fst'

val x : 'a

val fib' : _arg1:int -> int



Full name: fsharpcheatsheet.fib'





Similar to `fib`; using `function` for pattern matching

val list1 : string list



Full name: fsharpcheatsheet.list1

val list2 : string list



Full name: fsharpcheatsheet.list2

val list3 : string list



Full name: fsharpcheatsheet.list3

val sum : list:int list -> int



Full name: fsharpcheatsheet.sum

Multiple items

val list : int list



--------------------

type 'T list = List<'T>



Full name: Microsoft.FSharp.Collections.list<_>

val xs : int list

val array1 : string []



Full name: fsharpcheatsheet.array1

val first : string



Full name: fsharpcheatsheet.first

val seq1 : seq<int>



Full name: fsharpcheatsheet.seq1

Multiple items

val seq : sequence:seq<'T> -> seq<'T>



Full name: Microsoft.FSharp.Core.Operators.seq



--------------------

type seq<'T> = System.Collections.Generic.IEnumerable<'T>



Full name: Microsoft.FSharp.Collections.seq<_>

val xs : int list



Full name: fsharpcheatsheet.xs

val ys : int []



Full name: fsharpcheatsheet.ys

val i : int

val zs : int list



Full name: fsharpcheatsheet.zs

Multiple items

module List



from Microsoft.FSharp.Collections



--------------------

type List<'T> =

| ( [] )

| ( :: ) of Head: 'T * Tail: 'T list

interface IEnumerable

interface IEnumerable<'T>

member Head : 'T

member IsEmpty : bool

member Item : index:int -> 'T with get

member Length : int

member Tail : 'T list

static member Cons : head:'T * tail:'T list -> 'T list

static member Empty : 'T list



Full name: Microsoft.FSharp.Collections.List<_>

val init : length:int -> initializer:(int -> 'T) -> 'T list



Full name: Microsoft.FSharp.Collections.List.init

val xs' : string



Full name: fsharpcheatsheet.xs'

val fold : folder:('State -> 'T -> 'State) -> state:'State -> array:'T [] -> 'State



Full name: Microsoft.FSharp.Collections.Array.fold

val str : string

val sprintf : format:Printf.StringFormat<'T> -> 'T



Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf

val last : xs:'a list -> 'a



Full name: fsharpcheatsheet.last

val xs : 'a list

val reduce : reduction:('T -> 'T -> 'T) -> list:'T list -> 'T



Full name: Microsoft.FSharp.Collections.List.reduce

val acc : 'a

val ys' : int []



Full name: fsharpcheatsheet.ys'

val iter : action:('T -> unit) -> list:'T list -> unit



Full name: Microsoft.FSharp.Collections.List.iter

val zs' : seq<int>



Full name: fsharpcheatsheet.zs'

val x : int * string



Full name: fsharpcheatsheet.x

val y : string * string * string



Full name: fsharpcheatsheet.y

val a' : int



Full name: fsharpcheatsheet.a'

val b' : string



Full name: fsharpcheatsheet.b'

val c' : int



Full name: fsharpcheatsheet.c'

val fst : tuple:('T1 * 'T2) -> 'T1



Full name: Microsoft.FSharp.Core.Operators.fst

val d' : int



Full name: fsharpcheatsheet.d'

val snd : tuple:('T1 * 'T2) -> 'T2



Full name: Microsoft.FSharp.Core.Operators.snd

val print' : 'a * 'b -> unit



Full name: fsharpcheatsheet.print'

val tuple : 'a * 'b

val a : 'a

val b : 'b

type Person =

{Name: string;

Age: int;}

member Info : string * int



Full name: fsharpcheatsheet.Person

Person.Name: string

Person.Age: int

Multiple items

val int : value:'T -> int (requires member op_Explicit)



Full name: Microsoft.FSharp.Core.Operators.int



--------------------

type int = int32



Full name: Microsoft.FSharp.Core.int



--------------------

type int<'Measure> = int



Full name: Microsoft.FSharp.Core.int<_>

val paul : Person



Full name: fsharpcheatsheet.paul

val paulsTwin : Person



Full name: fsharpcheatsheet.paulsTwin

val x : Person

member Person.Info : string * int



Full name: fsharpcheatsheet.Person.Info

val isPaul : person:Person -> bool



Full name: fsharpcheatsheet.isPaul

val person : Person

type Tree<'T> =

| Node of Tree<'T> * 'T * Tree<'T>

| Leaf



Full name: fsharpcheatsheet.Tree<_>

union case Tree.Node: Tree<'T> * 'T * Tree<'T> -> Tree<'T>

union case Tree.Leaf: Tree<'T>

val depth : _arg1:Tree<'a> -> int



Full name: fsharpcheatsheet.depth

val l : Tree<'a>

val r : Tree<'a>

val max : e1:'T -> e2:'T -> 'T (requires comparison)



Full name: Microsoft.FSharp.Core.Operators.max

val optionPatternMatch : input:int option -> unit



Full name: fsharpcheatsheet.optionPatternMatch

val input : int option

union case Option.Some: Value: 'T -> Option<'T>

union case Option.None: Option<'T>

type OrderId = | Order of string



Full name: fsharpcheatsheet.OrderId

union case OrderId.Order: string -> OrderId

val orderId : OrderId



Full name: fsharpcheatsheet.orderId

val id : string



Full name: fsharpcheatsheet.id

val divideFailwith : x:int -> y:int -> int



Full name: fsharpcheatsheet.divideFailwith

val y : int

val failwith : message:string -> 'T



Full name: Microsoft.FSharp.Core.Operators.failwith

val divide : x:int -> y:int -> int option



Full name: fsharpcheatsheet.divide

namespace System

Multiple items

type DivideByZeroException =

inherit ArithmeticException

new : unit -> DivideByZeroException + 2 overloads



Full name: System.DivideByZeroException



--------------------

System.DivideByZeroException() : unit

System.DivideByZeroException(message: string) : unit

System.DivideByZeroException(message: string, innerException: exn) : unit

exception InnerError of string



Full name: fsharpcheatsheet.InnerError

exception OuterError of string



Full name: fsharpcheatsheet.OuterError

val handleErrors : x:'a -> y:'a -> unit (requires equality)



Full name: fsharpcheatsheet.handleErrors

val x : 'a (requires equality)

val y : 'a (requires equality)

val raise : exn:System.Exception -> 'T



Full name: Microsoft.FSharp.Core.Operators.raise

Multiple items

type Vector =

new : x:float * y:float -> Vector

member Scale : s:float -> Vector

member Mag : float

member X : float

member Y : float

static member ( + ) : a:Vector * b:Vector -> Vector



Full name: fsharpcheatsheet.Vector



--------------------

new : x:float * y:float -> Vector

val x : float

Multiple items

val float : value:'T -> float (requires member op_Explicit)



Full name: Microsoft.FSharp.Core.Operators.float



--------------------

type float = System.Double



Full name: Microsoft.FSharp.Core.float



--------------------

type float<'Measure> = float



Full name: Microsoft.FSharp.Core.float<_>

val y : float

val mag : float

val sqrt : value:'T -> 'U (requires member Sqrt)



Full name: Microsoft.FSharp.Core.Operators.sqrt

val this : Vector

member Vector.X : float



Full name: fsharpcheatsheet.Vector.X

member Vector.Y : float



Full name: fsharpcheatsheet.Vector.Y

member Vector.Mag : float



Full name: fsharpcheatsheet.Vector.Mag

member Vector.Scale : s:float -> Vector



Full name: fsharpcheatsheet.Vector.Scale

val s : float

val a : Vector

val b : Vector

property Vector.X: float

property Vector.Y: float

Multiple items

type Animal =

new : unit -> Animal

member Rest : unit -> unit



Full name: fsharpcheatsheet.Animal



--------------------

new : unit -> Animal

member Animal.Rest : unit -> unit



Full name: fsharpcheatsheet.Animal.Rest

Multiple items

type Dog =

inherit Animal

new : unit -> Dog

member Run : unit -> unit



Full name: fsharpcheatsheet.Dog



--------------------

new : unit -> Dog

member Dog.Run : unit -> unit



Full name: fsharpcheatsheet.Dog.Run

val dog : Dog



Full name: fsharpcheatsheet.dog

val animal : Animal



Full name: fsharpcheatsheet.animal

val shouldBeADog : Dog



Full name: fsharpcheatsheet.shouldBeADog

type IVector =

interface

abstract member Scale : float -> IVector

end



Full name: fsharpcheatsheet.IVector

abstract member IVector.Scale : float -> IVector



Full name: fsharpcheatsheet.IVector.Scale

Multiple items

type Vector' =

interface IVector

new : x:float * y:float -> Vector'

member X : float

member Y : float



Full name: fsharpcheatsheet.Vector'



--------------------

new : x:float * y:float -> Vector'

override Vector'.Scale : s:float -> IVector



Full name: fsharpcheatsheet.Vector'.Scale

val __ : Vector'

member Vector'.X : float



Full name: fsharpcheatsheet.Vector'.X

member Vector'.Y : float



Full name: fsharpcheatsheet.Vector'.Y

type ICustomer =

interface

abstract member Age : int

abstract member Name : string

end



Full name: fsharpcheatsheet.ICustomer

abstract member ICustomer.Name : string



Full name: fsharpcheatsheet.ICustomer.Name

abstract member ICustomer.Age : int



Full name: fsharpcheatsheet.ICustomer.Age

val createCustomer : name:string -> age:int -> ICustomer



Full name: fsharpcheatsheet.createCustomer

val name : string

val age : int

val __ : ICustomer

property ICustomer.Age: int

val testNumber : i:int -> unit



Full name: fsharpcheatsheet.testNumber

active recognizer Even: int -> Choice<unit,unit>



Full name: fsharpcheatsheet.( |Even|Odd| )

active recognizer Odd: int -> Choice<unit,unit>



Full name: fsharpcheatsheet.( |Even|Odd| )

val by : int

val fizzBuzz : _arg1:int -> string



Full name: fsharpcheatsheet.fizzBuzz

active recognizer DivisibleBy: int -> int -> unit option



Full name: fsharpcheatsheet.( |DivisibleBy|_| )

val path : string



Full name: fsharpcheatsheet.path