I was originally going to include this discussion about F# enumerations in the discriminated unions post because their syntax is so similar but the section quickly took on a life of its own. Enumerations in F# are the same as enumerations from other .NET languages so all of the same capabilities and restrictions apply.
Defining Enumerations
Defining an enumeration in F# is much like defining a discriminated union but here we bind an integral value. Unlike in C# though, F# doesn’t automatically generate values for each item so we need to give every case a value.
type DayOfWeek = | Sunday = 0 | Monday = 1 | Tuesday = 2 | Wednesday = 3 | Thursday = 4 | Friday = 5 | Saturday = 6
Changing Base Type
We can also change the enumeration’s underlying type by changing the suffix of each value. For example, if we wanted to change the underlying type for the DayOfWeek enumeration to byte we could do so by appending a y to each value as follows:
type DayOfWeekByte = | Sunday = 0y | Monday = 1y | Tuesday = 2y | Wednesday = 3y | Thursday = 4y | Friday = 5y | Saturday = 6y
Referencing Enumeration Values
As is the case with enumerations in other .NET languages enumeration values are referenced through the enumeration name.
> DayOfWeek.Friday val it : DayOfWeek = Friday
FlagsAttribute
Also like in other .NET languages, F# enumerations support the FlagsAttribute to indicate that each value in the enumeration represents a bit position.
open System [<Flags>] type Border = | None = 0 | Right = 1 | Top = 2 | Left = 4 | Bottom = 8;; let showBorder = Border.Bottom ||| Border.Left
To determine whether a particular flag is set we can either use bit-math or we can use the enumeration’s HasFlag method. Since I generally prefer the code I don’t have to write so I generally favor built-in approach:
> showBorder.HasFlag Border.Top;; val it : bool = false > showBorder.HasFlag Border.Left;; val it : bool = true
Conversion
For those times when we only have the underlying integer value and want to convert that value to the corresponding enum value we can use the built-in generic enum function:
> enum<DayOfWeek> 5 val it : DayOfWeek = Friday
Note: The signature of the enum function above is int32 -> 'U so it can only be used with enumerations based on int32. If your enumeration is based on another data type such as with the DayOfWeekByte example above you’ll need to use the generic EnumOfValue function from the Microsoft.FSharp.Core.LanguagePrimitives module instead.
Likewise, we can get the underlying value by calling the corresponding conversion function:
int DayOfWeek.Friday // val it : int = 5 byte DayOfWeekByte.Friday // val it : byte = 5uy