ZetCode

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.

main.fsx
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.

main.fsx
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.

main.fsx
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.

main.fsx
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.

main.fsx
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.

main.fsx
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.

main.fsx
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.

main.fsx
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

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.