F# Snippet – Enums and Discriminated Unions

I was writing some F# code this week and ran into problem. Consider the following code:


type Thingey = This | That | SomethingElse


Which looks like an enum. So I assumed that, like things inheriting from System.Enum, an instance of the type had a ToString method which did the right thing. But, alas, when I type it into the F# Interactive Console I get:


> (Thingey.That).ToString();;

val it : string = “FSI_0002+Thingey”


The reason being is that the type Thingey is actually a Discriminated Union. In F#, to produce an Enumeration type you use the same syntax except you must explicitly provide an integer value for each member. Discriminated Unions can do a lot more than Enums in F#, but there are situations in which to use both.


The following snippet shows you how to use Enums and simple Discriminated Union types in F#.




open System


// Enum type.

type FruitEnum =

    | Apple   = 0

    | Pear    = 1

    | Orange  = 2

    | Bananna = 3


// Enums have nice built in methods to parse and get their values.

// Note the “typeof<FruitEnum>” syntax to get get the typeof an F# object.

let favoriteFruit = Enum.Parse(typeof<FruitEnum>, “Pear”)

let allFruit = Enum.GetValues(typeof<FruitEnum>)


// You can even do some pattern matching…

let isGreen (day : FruitEnum) =

    match day with

    | FruitEnum.Apple | FruitEnum.Pear -> true

    | _ -> false


// Consider the following. Leads to undefined results, but

// is valid! This is because any int can be cast to/from an

// enum.

isGreen (Enum.of_int 99999)


// Now consider Discriminated Unions. One of their nice features is that the compiler can enforce

// some nice constraints when pattern matching; such as incomplete or too complete matchings.

type Shape =

    | Circle

    | Square

    | Triangle


// Warning: too few items. Pattern Matching incomplete.

let isRound x =

    match x with

    | Circle -> true

    | Square -> false

    // Warning FS0025: Incomplete pattern matches on this expression.


// Warning: too many items. (Matches more than every item.)

let isSquare x =

    match x with

    | Circle -> false

    | Square -> true

    | Triangle -> false

    | _ -> false

    // Warning FS0026: This rule will never be matched.

Comments (1)

  1. I was writing some F# code this week and ran into problem. Consider the following code: type Thingey