Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
204 views

Fsharp Cheatsheet

This document provides a summary of common F# syntax elements in 3 sentences or less: Functions are defined using the let keyword, comments begin with (* and end with *) for blocks or // for lines, and pattern matching is used to decompose values and handle different cases. Tuples group unnamed values, records bundle named values, and discriminated unions define tagged union types. Classes can inherit from other classes and interfaces, active patterns parse input values, and compiler directives like #load and #r control code loading and referencing.

Uploaded by

rajeevsahani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
204 views

Fsharp Cheatsheet

This document provides a summary of common F# syntax elements in 3 sentences or less: Functions are defined using the let keyword, comments begin with (* and end with *) for blocks or // for lines, and pattern matching is used to decompose values and handle different cases. Tuples group unnamed values, records bundle named values, and discriminated unions define tagged union types. Classes can inherit from other classes and interfaces, active patterns parse input values, and compiler directives like #load and #r control code loading and referencing.

Uploaded by

rajeevsahani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

F# Cheatsheet

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.

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

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"

let fst (x, _) = x

Pipe and composition operators

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


let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)

Pipe operator |> is used to chain functions and arguments


together. Double-backtick identifiers are handy to improve
readability especially in unit testing:

For more complete reference visit Pattern Matching (MSDN).

This operator is essential in assisting the F# type checker by


providing type information before use:

Lists

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

let squareNegateThenPrint =
square >> negate >> print

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

Recursive functions

Backslash strings indent string contents by stripping leading


spaces.

The rec keyword is used together with the let keyword to


define a recursive function:

let poem =
"The lesser world was daubed\n\
By a colorist of modest skill\n\
A master limned you in the finest inks\n\
And with a fresh-cut quill."

let rec fact x =


if x < 1 then 1
else x * fact (x - 1)

Most numeric types have associated suffixes, e.g., uy for


unsigned 8-bit integers and L for signed 64-bit integer.

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
val
val
val

s : float32 = 4.14f
f : float = 4.14
d : decimal = 0.7833M
bi : System.Numerics.BigInteger = 9999

See Literals (MSDN) for complete reference.

// 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.

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)

// Arrays use square brackets with bar


let array1 = [| "a"; "b" |]
// Indexed access using dot
let first = array1.[0]

Sequences

let b, i, l = 86uy, 86, 86L


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

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

let sumOfLengths (xs : string []) =


xs
|> Array.map (fun s -> s.Length)
|> Array.sum
Composition operator is used to compose functions:

Basic Types and Literals

or implicitly via function keyword:

let square, negate, then print x =


x |> square |> negate |> print

Use verbatim strings preceded by @ symbol to avoid escaping


control characters (except escaping " by "").
We dont even have to escape " with triple-quoted strings.

Pattern matching can be done directly on arguments:

let squareNegateThenPrint x =
print (negate (square x))

(* This is block comment *)


// And this is line comment

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

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.

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:

// 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 |]

Exceptions

let c = fst (1, 2)


let d = snd (1, 2)

The failwith function throws an exception of type Exception.

let print tuple =


match tuple with
| (a, b) -> printfn "Pair %A %A" a b

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

Records represent simple aggregates of named values,


optionally with members:

Exception handling is done via try/with expressions.

// Declare a record type


type Person = { Name : string; Age : int }

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 doesnt 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 |]
iterate through a list and produce side effects
List.iter (fun x -> printfn "%i" x) [ 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:

// 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

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. Heres 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."

Discriminated unions (DU) provide support for values that


can be one of a number of named cases, each possibly with
different values and types.

Classes and Inheritance

type Tree<T> =
| Node of Tree<T> * T * Tree<T>
| Leaf

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)

let rec depth = function


| Node(l, _, r) -> 1 + depth l + depth r
| Leaf -> 0
F# Core has a few built-in discriminated unions for error
handling, e.g., Option and Choice.

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

let optionPatternMatch input =


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

Call a base class from a derived one.

Single-case discriminated unions are often used to create


type-safe abstractions with pattern matching support:

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

type OrderId = Order of string

type Animal() =
member __.Rest() = ()

Upcasting is denoted by :> operator.

// Create a DU value
let orderId = Order "12"

let dog = Dog()


let animal = dog :> Animal

// Pattern matching of single-case DU


let (Order id) = orderId

Dynamic casting (:?>) might throw an exception if the cast


doesnt succeed at runtime.

let probablyADog = 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 }

Partial active patterns share the syntax of parameterized


patterns but their active recognizers accept only one argument.

Active Patterns

Compiler Directives

Complete active patterns:

Load another F# source file into FSI.

let (|Even|Odd|) i =
if i % 2 = 0 then Even else Odd

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

let testNumber i =
match i with
| Even -> printfn "%d is even" i
| Odd -> printfn "%d is odd" i
Parameterized active patterns:

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"

let (|DivisibleBy|_|) by n =
if n % by = 0 then Some DivisibleBy else None

Other important directives are conditional execution in FSI


(INTERACTIVE) and querying current directory
(__SOURCE_DIRECTORY__).

let fizzBuzz = function


| DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz"
| DivisibleBy 3 -> "Fizz"
| DivisibleBy 5 -> "Buzz"
| _ -> ""

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

You might also like