You are on page 1of 3

F# Cheatsheet let s, f, d, bi = 4.14F, 4.14, 0.

7833M, 9999I Pattern Matching


Pattern matching is often facilitated through match keyword.
This cheatsheet glances over some of the common syntax of val s : float32 = 4.14f
let rec fib n =
F# 3.0. If you have any comments, corrections, or suggested val f : float = 4.14
match n with
additions, please open an issue or send a pull request to val d : decimal = 0.7833M
| 0 -> 0
https://github.com/dungpa/fsharp-cheatsheet. val bi : System.Numerics.BigInteger = 9999
| 1 -> 1
Comments | _ -> fib (n - 1) + fib (n - 2)
See Literals (MSDN) for complete reference.
Block comments are placed between (* and *). Line
comments start from // and continue until the end of the line. Functions In order to match sophisticated inputs, one can use when to
The let keyword also defines named functions. create filters or guards on patterns:
(* This is block comment *)
let negate x = x * -1 let sign x =
// And this is line comment let square x = x * x match x with
let print x = printfn "The number is: %d" x | 0 -> 0
| x when x < 0 -> -1
XML doc comments come after /// allowing us to use XML let squareNegateThenPrint x = | x -> 1
tags to generate documentation. print (negate (square x))
/// The let keyword defines an (immutable) value Pattern matching can be done directly on arguments:
let result = 1 + 1 = 2 Pipe and composition operators let fst (x, _) = x
Pipe operator |> is used to chain functions and arguments
Strings together. Double-backtick identifiers are handy to improve or implicitly via function keyword:
F# string type is an alias for System.String type. readability especially in unit testing:
/// Similar to fib; using function for pattern matching
/// Create a string using string concatenation let square, negate, then print x = let rec fib = function
let hello = "Hello" + " World" x |> square |> negate |> print | 0 -> 0
| 1 -> 1
This operator is essential in assisting the F# type checker by | n -> fib (n - 1) + fib (n - 2)
Use verbatim strings preceded by @ symbol to avoid escaping
providing type information before use:
control characters (except escaping " by "").
let sumOfLengths (xs : string []) = For more complete reference visit Pattern Matching (MSDN).
let verbatimXml = @"<book title=""Paradise Lost"">" xs
|> Array.map (fun s -> s.Length) Collections
We dont even have to escape " with triple-quoted strings. |> Array.sum Lists
let tripleXml = """<book title="Paradise Lost">""" A list is an immutable collection of elements of the same type.
Composition operator is used to compose functions:
// Lists use square brackets and ; delimiter
Backslash strings indent string contents by stripping leading let squareNegateThenPrint = let list1 = [ "a"; "b" ]
spaces. square >> negate >> print // :: is prepending
let list2 = "c" :: list1
let poem =
Recursive functions // @ is concat
"The lesser world was daubed\n\
let list3 = list1 @ list2
By a colorist of modest skill\n\ The rec keyword is used together with the let keyword to
A master limned you in the finest inks\n\ define a recursive function:
// Recursion on list using (::) operator
And with a fresh-cut quill." let rec fact x = let rec sum list =
if x < 1 then 1 match list with
else x * fact (x - 1) | [] -> 0
Basic Types and Literals
| x :: xs -> x + sum xs
Most numeric types have associated suffixes, e.g., uy for
Mutually recursive functions (those functions which call each
unsigned 8-bit integers and L for signed 64-bit integer.
other) are indicated by and keyword:
let b, i, l = 86uy, 86, 86L Arrays
let rec even x =
if x = 0 then true Arrays are fixed-size, zero-based, mutable collections of
val b : byte = 86uy else odd (x - 1) consecutive data elements.
val i : int = 86 // Arrays use square brackets with bar
val l : int64 = 86L and odd x = let array1 = [| "a"; "b" |]
if x = 1 then true // Indexed access using dot
Other common examples are F or f for 32-bit floating-point else even (x - 1) let first = array1.[0]
numbers, M or m for decimals, and I for big integers.

1
Sequences Tuples and Records let rec depth = function
A sequence is a logical series of elements of the same type. A tuple is a grouping of unnamed but ordered values, possibly | Node(l, _, r) -> 1 + max (depth l) (depth r)
Individual sequence elements are computed only as required, of different types: | Leaf -> 0
so a sequence can provide better performance than a list in // Tuple construction
situations in which not all the elements are used. let x = (1, "Hello") F# Core has a few built-in discriminated unions for error
// Sequences can use yield and contain subsequences handling, e.g., Option and Choice.
let seq1 = // Triple let optionPatternMatch input =
seq { let y = ("one", "two", "three") match input with
// "yield" adds one element | Some i -> printfn "input is an int=%d" i
yield 1 // Tuple deconstruction / pattern | None -> printfn "input is missing"
yield 2 let (a, b) = x

// "yield!" adds a whole subsequence Single-case discriminated unions are often used to create
The first and second elements of a tuple can be obtained using
yield! [5..10] type-safe abstractions with pattern matching support:
fst, snd, or pattern matching:
} type OrderId = Order of string
let c = fst (1, 2)
let d = snd (1, 2)
Higher-order functions on collections // Create a DU value
let print tuple = let orderId = Order "12"
The same list [ 1; 3; 5; 7; 9 ] or array [| 1; 3; 5; 7; 9
|] can be generated in various ways. match tuple with
| (a, b) -> printfn "Pair %A %A" a b // Use pattern matching to deconstruct single-case DU
Using range operator .. let (Order id) = orderId
let xs = [ 1..2..9 ] Records represent simple aggregates of named values,
Using list or array comprehensions
optionally with members: Exceptions
// Declare a record type The failwith function throws an exception of type Exception.
let ys = [| for i in 0..4 -> 2 * i + 1 |] type Person = { Name : string; Age : int }
let divideFailwith x y =
Using init function if y = 0 then
// Create a value via record expression
let zs = List.init 5 (fun i -> 2 * i + 1) failwith "Divisor cannot be zero."
let paul = { Name = "Paul"; Age = 28 }
else x / y
Lists and arrays have comprehensive sets of higher-order
functions for manipulation. // Copy and update record expression
let paulsTwin = { paul with Name = "Jim" } Exception handling is done via try/with expressions.
fold starts from the left of the list (or array) and
foldBack goes in the opposite direction let divide x y =
Records can be augmented with properties and methods: try
let xs = Array.fold (fun str n -> type Person with Some (x / y)
sprintf "%s,%i" str n) "" [| 0..9 |] member x.Info = (x.Name, x.Age) with :? System.DivideByZeroException ->
reduce doesnt require an initial accumulator printfn "Division by zero!"
None
let last xs = List.reduce (fun acc x -> x) xs Records are essentially sealed classes with extra topping:
default immutability, structural equality, and pattern
map transforms every element of the list (or array) matching support. The try/finally expression enables you to execute clean-up
let isPaul person = code even if a block of code throws an exception. Heres an
let ys = Array.map (fun x -> x * x) [| 0..9 |]
match person with example which also defines custom exceptions.
iterate through a list and produce side effects | { Name = "Paul" } -> true exception InnerError of string
let _ = List.iter (printfn "%i") [ 0..9 ] | _ -> false exception OuterError of string

All these operations are also available for sequences. The let handleErrors x y =
added benefits of sequences are laziness and uniform treatment Discriminated Unions try
of all collections implementing IEnumerable<T>. Discriminated unions (DU) provide support for values that try
let zs = can be one of a number of named cases, each possibly with if x = y then raise (InnerError("inner"))
seq { different values and types. else raise (OuterError("outer"))
for i in 0..9 do type Tree<T> = with InnerError(str) ->
printfn "Adding %d" i | Node of Tree<T> * T * Tree<T> printfn "Error1 %s" str
yield i | Leaf finally
} printfn "Always print this."

2
Classes and Inheritance Interfaces and Object Expressions Parameterized active patterns:
This example is a basic class with (1) local let bindings, (2) Declare IVector interface and implement it in Vector. let (|DivisibleBy|_|) by n =
properties, (3) methods, and (4) static members. type IVector = if n % by = 0 then Some DivisibleBy else None
abstract Scale : float -> IVector
type Vector(x : float, y : float) = let fizzBuzz = function
let mag = sqrt(x * x + y * y) // (1) type Vector(x, y) = | DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz"
member this.X = x // (2) interface IVector with | DivisibleBy 3 -> "Fizz"
member this.Y = y member __.Scale(s) = | DivisibleBy 5 -> "Buzz"
member this.Mag = mag Vector(x * s, y * s) :> IVector | i -> string i
member this.Scale(s) = // (3) member __.X = x
Vector(x * s, y * s) member __.Y = y Partial active patterns share the syntax of parameterized
static member (+) (a : Vector, b : Vector) = // (4) patterns but their active recognizers accept only one argument.
Vector(a.X + b.X, a.Y + b.Y)
Another way of implementing interfaces is to use object Compiler Directives
expressions.
Load another F# source file into FSI.
Call a base class from a derived one. type ICustomer = #load "../lib/StringParsing.fs"
type Animal() = abstract Name : string
member __.Rest() = () abstract Age : int
Reference a .NET assembly (/ symbol is recommended for
let createCustomer name age = Mono compatibility).
type Dog() =
inherit Animal() { new ICustomer with #r "../lib/FSharp.Markdown.dll"
member __.Run() = member __.Name = name
base.Rest() member __.Age = age } Include a directory in assembly search paths.
#I "../lib"
Upcasting is denoted by :> operator. Active Patterns #r "FSharp.Markdown.dll"
Complete active patterns:
let dog = Dog() Other important directives are conditional execution in FSI
let (|Even|Odd|) i =
let animal = dog :> Animal (INTERACTIVE) and querying current directory
if i % 2 = 0 then Even else Odd
(__SOURCE_DIRECTORY__).
Dynamic downcasting (:?>) might throw an let testNumber i = #if INTERACTIVE
InvalidCastException if the cast doesnt succeed at runtime. match i with let path = __SOURCE_DIRECTORY__ + "../lib"
| Even -> printfn "%d is even" i #else
let shouldBeADog = animal :?> Dog | Odd -> printfn "%d is odd" i let path = "../../../lib"
#endif

You might also like