Getting started

Hello world

Basic F# program

open System

let greetMe name =
    sprintf "Hello, %s!" name

[<EntryPoint>]
let main argv =
    let message = greetMe "World"
    printfn "%s" message
    0
dotnet run

Download .NET Core to run on your machine.

Values

let bindings define immutable values

let x = 12
let name = "Don Syme"

let mutable defines a mutable value

let mutable x = 12
x <- 13

Bindings are immutable by default in F#. See Values for more.

Functions

let bindings define functions

let square x = x * x

let isOdd x = x % 2 <> 0

Use |> to chain function calls together

let sumOfOddSquares items =
    items
    |> List.filter isOdd
    |> List.sumBy square

Functions are first-class in F#. See Functions for more.

Basic types

Strings

let s1 = "this is a string"
let s2 = @"this is a verbatim string"
let s3 =
    """
        this is a verbatim string
        that lets you use quotes ""!
    """

Strings all are of type String in .NET.

Common Types

Basic numeric types

let x = 1      // int
let y = 1.0    // float
let z = 1.0m   // decimal

Other numeric types

let x = 1u       // unsigned int
let y = 1uy      // unsigned byte
let z = 2.3E+32  // other float notation

See Literals for more.

Unit

// Function that takes nothing as does nothing
let f () = ()

let x = ()

// Ignore function produces nothing as output
12 |> ignore

Unit indicates the absence of a value. See Unit Type for more.

Basic collections

Lists

Lists use [ ] syntax

let xs = [ 1; 2; 3; 4; 5 ]
let ys = [
    1
    2
]

let zs = xs |> List.map (fun x -> x + 1)
// [ 2; 3; 4; 5; 6 ]

List expressions and slices

let evensUnderTen =
    [ 1 .. 10 ]
    |> List.filter (fun x -> x % 2 = 0)

let tenSquares =
    [ for x in 1 .. 10 -> x * x ]

let nested = [ [1; 2]; [3; 4]; [5; 6] ]

let lst = [ for l in nested do
                for x in l ->  x * x ]
// [ 1; 4; 9; 16; 25; 36 ]

Lists are immutable, singly-linked lists.

Arrays

Arrays use [| |] syntax

let xs = [| 1; 2; 3; 4; 5 |]
let ys = [|
    1
    2
|]

ys.[0] <- 5 // Change first item to be 5

let zs = xs |> Array.map (fun x -> x + 1)
// [| 2; 3; 4; 5; 6 |]

Array expressions and slices

let evensUnderTen =
    [| 1 .. 10 |]
    |> Array.filter (fun x -> x % 2 = 0)

let tenSquares =
    [| for x in 1 .. 10 -> x * x |]

let nested = [| [1; 2]; [3; 4]; [5; 6] |]

let lst = [| for l in nested do
                 for x in l ->  x * x |]
// [| 1; 4; 9; 16; 25; 36 |]

Arrays have mutable contents.

Sequences

Seq uses seq { } syntax

let xs = seq { yield 1; yield 2 }
let ys = [|
    yield 1
    yield 2
|]

let zs = xs |> Seq.map (fun x -> x + 1)
// seq [2; 3]

Seq expressions

// Fibonacci sequence
let rec fibs = seq {
    yield 0
    yield 1
    yield!
        fibs
        |> Seq.map2 (+) (fibs |> Seq.skip 1)
}

let firstTen = Seq.take 10 fibs
// seq [0; 1; 1; 2; ...]

Sequences are lazily-computed, so they can represent infinite sets.

Data types

Records

Record declaration

type CartItem =
    { ProductCode: string;
      Qty: int }
type ActiveCartData =
    { UnpaidItems: CartItem list }

type PaidCartData =
    { PaidItems: CartItem list
      Payment: decimal }

Record instantiation and usage

// Records are created with a similar syntax
let cartItem =
    { ProductCode = "MyProductCode"
      Qty = 2 }

// Copy and Update syntax
let cartItem2 = { cartItem with Qty = 3 }

// Use '.' syntax to access data
printfn "Quantity: %d" cartItem.Qty

See Records for more.

Discriminated Unions

Discriminated Union declaration

// Simple DU handling various cases
type Shape =
    | Circle of float
    | EquilateralTriangle of double
    | Square of double
    | Rectangle of double * double

// Recursively-defined DU with generics
type BST<'T> =
    | Empty
    | Node of 'T * BST<'T> * BST<'T>

Discriminated Union instantiation

let circle = Circle 2.0f
let rectangle = Rectangle(3.0f, 4.0f)

// Single-node binary search tree
let bst = Node("hello", Empty, Empty)

See Discriminated Unions for more.

Units of Measure

Units of Measure declaration

// Define a new UoM
[<Measure>]
type cm

// Define a UoM based on an existing one
[<Measure>]
type ml = cm^3

Units of measure usage

// Unit conversions
let convertg2kg (x: float<g>) =
    x / 1000.0<g/kg>

// Extracting a scalar value
let unwrap (x: int<m>) =
    x / 1<m>

See Units of Measure for more.

Pattern Matching

match expressions

Match on discriminated unions

type Color = Red | Blue | Yellow

// val colorName : Color -> string
let colorName color =
    match color with
    | Red -> "red"
    | Blue -> "blue"
    | Yellow -> "yellow"

Match on other data

// You can match on any data type,
// but you may need a discard case at the end.
let getName name =
    match name with
    | "Phillip" -> printfn "Hello, Phillip!"
    | "Ali" -> printfn "Hello, Ali!"
    | _ -> printfn "Goodbye!"

function keyword

Partially apply pattern matching

open System

// Same DU as before
type Shape =
    | Circle of float
    | EquilateralTriangle of double
    | Square of double
    | Rectangle of double * double

// Partially applied Shape argument:
//
// val calcArea : (Shape -> float)
let calcArea = function
    | Circle r -> 2.0 * Math.PI * r
    | EquilateralTriangle s ->
        s * s * sqrt(3.0) / 4.0
    | Square s -> s * s
    | Rectangle(l, w) -> l * w

Destructuring data

Pull data out of types

type Data = String of string | Int of int

let (String s) = getData()
printfn "String length: %d" s.Length

// Tuple destructuring
let (x, y) = (1, 2)

See Pattern Matching for more.

Object programming

Classes

Class declaration with members and interface implementation

type CustomerName(first, middle, last) =
    member this.FirstName = first
    member this.MiddleName = middle
    member this.LastName = last

    member this.PrintName() =
        printfn "%s %s %s" first middle last

    interface System.IDisposable with
        member __.Dispose() =
            printfn "Disposing....!"

Abstract classes

Declared with a default implementation

type MathService() =
    abstract Add: int -> int -> int
    abstract Mult: int -> int -> int

    default this.Add x y = x + y
    default this.Mult x y = x * y

Declared without a default implementation

[<AbstractClass>]
type MathService() =
    abstract Add: int -> int -> int
    abstract Mult: int -> int -> int

Interfaces

Interface declaration

type IMathService =
    abstract Add: int -> int -> int
    abstract Mult: int -> int -> int

Object expressions to implement interfaces

let adhocMathSvc =
    { new IMathService with
          member __.Add x y = x + y
          member __.Mult x y = x * y }

let res1 = adhocMathSvc.Add 1 2
let res2 = adhocMathSvc.Mult 3 4

More Resources

0 Comments for this cheatsheet. Write yours!