How to prevent F# union case names leaking into parent scope

Suppose you are writing some F# code to model the workings of a coffee shop. You might start by defining a small choice of snacks:

type Cost = int

type Muffin =
| RaspberryAndWhiteChocolate of Cost
| Blueberry of Cost
                          
[<EntryPoint>]
let main argv = 
    // No need for "Muffin." qualifier on Blueberry
    let muffin = Blueberry 250 

    printfn "%A" muffin
    0

This compiles and runs just fine – notice that there’s no requirement to prefix the union case “Blueberry” with the type name “Muffin”. All is well.

However, suppose you then proceed to define some more types for coffee:

              
type Milk =
| Skimmed
| Whole
| SemiSkimmed

type Modifier =
| Milk of Milk
| Cream
| None   // <--- Oops, clashes with FSharpOption.None
             
type Coffee =
| Filter of Modifier
| Cappuccino
| Latte

[<EntryPoint>]
let main argv = 

    let muffin = Blueberry 250

    let coffee = Filter( None )

    printfn "%A %A" muffin coffee
    0

This still compiles and runs – but there’s a lurking problem. As soon as you add the use of optional values, the program fails to compile. For example, you might offer free coffee as a promotion, and model the cost as optional:

    let coffee = Filter( None )
    let cost : int option = None

compileerror
The problem is that None is now used as both a union case in Modifier and a union case in FSharpOption.

Whilst you could choose to workaround this by changing the “None” union case in Modifier to “Nothing”, you may not have that flexibility. Instead, you can use the RequireQualifiedAccess attribute on the Modifier type to stop union case names leaking into the surrounding scope:

[<RequireQualifiedAccess>]
type Modifier =
| Milk of Milk
| Cream
| None 

[<EntryPoint>]
let main argv = 
    let muffin = Blueberry 250 // still no qualifier required
    let coffee = Filter( Modifier.None ) // now requires qualifier
    let cost : double option = None // ok, uses FSharpOption.None

    printfn "%A %A %A" muffin coffee cost
    0

Leave a comment

Filed under F#

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.