Pattern matching snippets

#light

open System

// *************************************************************

// * Pattern matching using match/with

// *************************************************************

// This is not legal, since DateTime.Today is a variable...

let dayDescriptor1 (day : DateTime) =

    match day with

    | DateTime.Today -> "today"

  | _ -> "not today"

// This is however, since the 'when guard' can be an expression

let dayDescriptor2 (day : DateTime) =

    match day with

    | _ when day = DateTime.Today -> "today"

    | _ -> "not today"

// *************************************************************

// * Pattern matching using functions

// *************************************************************

// The 'function' keyword is similar to 'fun', except that it

// only produces functions which take a single parameter and

// that parameter is treated as if it were put into a

// match/with block.

// For example, this function returns true IFF the tuple parameter

// is ("Chris", "Smith")

let isMe = function "Chris", "Smith" -> true

     | _, _ -> false

assert (isMe ("Bill", "Gates") = false)

// *************************************************************

// * Basic pattern matching using let bindings

// *************************************************************

// Assign two variables at once

let today, tomorrow = DateTime.Now, DateTime.Now.AddDays(1.0)

// Declare a list of elements, note that tail has value [4..100]

let a :: b :: c :: tail = [1..100]

// *************************************************************

// * Advanced pattern matching using let bindings

// *************************************************************

// Let's say you have a discriminated union...

type Foo = A of int | B of string * int

// You can use a pattern on the let binding to suck out the

// value from your discriminated union. This _greatly_

// cleans up code since you don't need a million

// match/with blocks.

let value = B("ZG", 7)

let A(x) | B(_, x) = value

assert (x = 7)

// You can use the same technique on records too...

type Party = Dem | Rep | Ind | Green | Other of string

type PresidentialCandidate = {Name : string; Party : Party}

let getCandidateName {Name = name ; Party = _ } = name

// Other ways to write the same method:

let getCandidateName2 = function {Name = name; Party = _} -> name

let getCandidateName3 candidate =

    match candidate with

        {Name = name; Party = _} -> name

// *************************************************************

// * The downside :(

// *************************************************************

// The following is legal code, but results in a runtime exception.

// I'll leave it as an exercise to the reader why this is allowed.

let 1 = 2