F# Enum Type
last modified May 24, 2025
This article explores how to effectively use enum types in F# to represent fixed sets of named values.
An enum type (or enumeration) is a distinct type consisting of a set of named constants. Enums provide a way to create meaningful symbolic names for values, making code more readable and maintainable. In F#, enums are value types that inherit from System.Enum.
F# supports two ways to create enums: using the type
keyword with
|
syntax for simple enumerations, and using the
[<Flags>]
attribute for bit flag enumerations. Enums can be
converted to and from their underlying integral types.
Basic enum definition
The simplest way to define an enum in F# is using discriminated union syntax.
type Color = | Red | Green | Blue | Yellow let favorite = Color.Blue match favorite with | Color.Red -> printfn "Your favorite color is Red" | Color.Green -> printfn "Your favorite color is Green" | Color.Blue -> printfn "Your favorite color is Blue" | Color.Yellow -> printfn "Your favorite color is Yellow"
This example demonstrates a basic color enum definition and pattern matching.
type Color = | Red | Green | Blue | Yellow
This defines a simple enum type with four possible values. Each value is a case of the discriminated union.
λ dotnet fsi main.fsx Your favorite color is Blue
Redundant Qualifiers
In F#, once you define a discriminated union type, you don't need to explicitly
reference its name when pattern matching. You can simply match against its cases
directly. This makes the Color
qualifier redundant when used inside
match
expressions.
type Color = | Red | Green | Blue | Yellow let favorite = Blue // No need for Color.Blue match favorite with | Red -> printfn "Your favorite color is Red" | Green -> printfn "Your favorite color is Green" | Blue -> printfn "Your favorite color is Blue" | Yellow -> printfn "Your favorite color is Yellow"
When referencing a case inside the same scope where Color
is
already recognized, F# infers that Red
,
Green
, Blue
, and Yellow
refer to the
Color
type. Thus, you can use the cases directly without
needing to prefix them with Color.
.
λ dotnet fsi main.fsx Your favorite color is Blue
Thus, explicitly prefixing cases with Color.
is unnecessary unless
there's ambiguity—like when multiple discriminated unions have overlapping
names. This behaviour is consistent across F# and helps keep the code
clean and concise.
Enum with underlying values
Enums can have explicit underlying values assigned to each case.
type Priority = | Low = 0 | Medium = 1 | High = 2 | Critical = 3 let currentPriority = Priority.High printfn "Priority value: %d" (int currentPriority) printfn "Priority name: %A" currentPriority
This example shows an enum with explicitly assigned integer values.
type Priority = | Low = 0 | Medium = 1 | High = 2 | Critical = 3
Each enum case is assigned a specific integer value. The int
function converts the enum to its underlying value.
λ dotnet fsi main.fsx Priority value: 2 Priority name: High
Flags enum
F# supports bit flag enums using the [<Flags>]
attribute.
open System [<Flags>] type Permissions = | None = 0 | Read = 1 | Write = 2 | Execute = 4 | All = 7 let userPermissions = Permissions.Read ||| Permissions.Write printfn "User permissions: %A" userPermissions printfn "Can read: %b" (userPermissions.HasFlag(Permissions.Read)) printfn "Can execute: %b" (userPermissions.HasFlag(Permissions.Execute))
This example demonstrates a flags enum for representing permission combinations.
[<Flags>] type Permissions = | None = 0 | Read = 1 | Write = 2 | Execute = 4 | All = 7
The [<Flags>]
attribute enables bitwise operations. Values
are powers of 2 to allow combination.
λ dotnet fsi main.fsx User permissions: Read, Write Can read: true Can execute: false
Enum parsing
Enums can be parsed from strings and converted to strings.
type Season = | Spring = 0 | Summer = 1 | Autumn = 2 | Winter = 3 let success, parsedSeason = System.Enum.TryParse<Season>("Summer") let seasonString = parsedSeason.ToString() printfn "Parse success: %b" success printfn "Parsed value: %A" parsedSeason printfn "String representation: %s" seasonString
This example shows how to convert between enums and strings.
let success, parsedSeason = System.Enum.TryParse<Season>("Summer")
Enum.TryParse
safely attempts to convert a string to an enum value.
λ dotnet fsi main.fsx Parse success: true Parsed value: Summer String representation: Summer
Enum iteration
You can iterate through all values of an enum type.
open System type Direction = | North = 0 | East = 1 | South = 2 | West = 3 let allDirections = Enum.GetValues(typeof<Direction>) printfn "All directions:" for dir in allDirections do printfn "- %A" dir
This example demonstrates how to get all values of an enum type.
let allDirections = Enum.GetValues(typeof<Direction>)
Enum.GetValues
returns an array containing all values of the enum.
λ dotnet fsi main.fsx All directions: - North - East - South - West
Enum with pattern matching
Enums work well with F#'s pattern matching feature.
type TrafficLight = | Red | Yellow | Green let getNextLight current = match current with | Red -> Green | Green -> Yellow | Yellow -> Red let light = TrafficLight.Red let nextLight = getNextLight light printfn "Current light: %A" light printfn "Next light: %A" nextLight
This example shows how to use pattern matching with enums.
match current with | Red -> Green | Green -> Yellow | Yellow -> Red
Pattern matching provides a clean way to handle different enum cases.
λ dotnet fsi main.fsx Current light: Red Next light: Green
Enum extension methods
You can extend enums with additional functionality.
type CardSuit = | Hearts = 0 | Diamonds = 1 | Clubs = 2 | Spades = 3 module CardSuitExtensions = type CardSuit with member this.Color = match this with | CardSuit.Hearts | CardSuit.Diamonds -> "Red" | CardSuit.Clubs | CardSuit.Spades -> "Black" | _ -> "Unknown" let suit = CardSuit.Hearts printfn "Suit: %A, Color: %s" suit (suit.Color)
This example adds a Color property to the CardSuit enum.
type CardSuit with member this.Color = match this with | CardSuit.Hearts | CardSuit.Diamonds -> "Red" | CardSuit.Clubs | CardSuit.Spades -> "Black" | _ -> "Unknown"
Extension methods allow adding functionality to existing enum types.
λ dotnet fsi main.fsx Suit: Hearts, Color: Red