Discriminated Unions In F#

A Discriminated Union (DU) is a feature provided by F# that allows you to define types which can be assigned a fixed set of values, each of which can have different types of data associated with it.

There are many uses of DU, including the modeling of complex data structures in a concise and expressive manner.

Throughout this article, we will take a look at what discriminated unions are, how they are defined, and some examples of how to use them in a F# project.

Syntax

The following syntax can be used to define discriminatory unions:

type type-name =
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ]
type2 ...]
| case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
...

As an example of how we might implement “choice” with a simple approach, we could describe it as follows:

type choice =
| Yes
| No

This example illustrates the use of the type choice in the following way:

Example: 

type choice = | Yes | Nolet a = Yes //create an instance of choice let b = No //create another instance of choice let main() = printfn "a: %A" a printfn "b: %A" b main()

The following output will be produced as a result:

Discriminated Unions



Voltage State on Choice Type

As an example, let us take a look at the voltage states that set a bit to either high or low using the following code:

Example: 

type VoltageState = | High | Lowlet Switch = function | High -> Low | Low -> Highlet main() = let on = High let off = Low let change = Switch offprintfn "Switch on: %A" on printfn "Switch off: %A" off printfn "Toggle off: %A" change printfn "Toggle Changed state: %A" (Switch change)main()

Discriminated Unions output


Area of Shape Using Choice Type

Using choice type below is an example of calculating the area of a square, circle and rectangle:

Example: 

type Shape = | Circle of float | Square of float | Rectangle of float * floatlet pi = 3.141592654 let area myShape = match myShape with | Circle radius -> pi * radius * radius | Square s -> s * s | Rectangle (length , width) -> length * widthlet radius = 8.0 let myCircle = Circle(radius) printfn "Area of circle with radius %g: %g" radius (area myCircle)let side = 12.0 let mySquare = Square(side) printfn "Area of square that has side %g: %g" side (area mySquare)let length , width = 3.0, 5.0 let myRectangle = Rectangle(length , width) printfn "Area of rectangle with length %g and width %g is %g" length width (area myRectangle)

And the output will be as follow:

Area of circle with radius 8: 201.061929856
Area of square that has side 12: 144
Area of rectangle with length 3 and width 5 is 15

Example Explanation:

This F# code defines a discriminated union called Shape with three cases: Circle, Square, and Rectangle. Each case contains different types of data, such as a radius for the Circle case and length and width for the Rectangle case.

The code also defines a function called area that takes a Shape as input and returns the area of that shape. The area function uses pattern matching to handle each case of the Shape union and calculate the area of the corresponding shape.

The code then creates instances of Shape using each case and prints the area of each shape using the area function. The printfn function formats and prints the results to the console.

For example, when the code is run, it creates a Circle with a radius of 8.0 and calculates its area using the area function. The code then prints the result to the console in the format “Area of circle with radius 8.0: <area>”. It does the same for a Square with a side length of 12.0 and a Rectangle with a length of 3.0 and width of 5.0.

This code demonstrates the power and flexibility of discriminated unions in F# for modeling complex data structures and algorithms.


Payment Method using Choice Type

Example: 

type PaymentMethod = | CreditCard of string * int * string | PayPal of string | BankTransfer of string * stringlet printPaymentMethod (method: PaymentMethod) = match method with | CreditCard (cardType, number, expiration) -> printfn "Credit card \nPayment method: %s \ncard ending at: %i \nexpiring on: %s" cardType number expiration | PayPal email -> printfn "\nPayPal payment method: %s" email | BankTransfer (bankName, accountNumber) -> printfn "\nBank transfer \nPayment method: account %s at bank %s" accountNumber bankNamelet creditcard = CreditCard("Purchase cards", 421215, "02/03/2025") printPaymentMethod creditcardlet paypal = PayPal("[email protected]") printPaymentMethod paypallet bank = BankTransfer("JPMorgan Chase","02230017345") printPaymentMethod bank

And the output will be:

Credit card
Payment method: Purchase cards
card ending at: 421215
expiring on: 02/03/2025

PayPal payment method: [email protected]

Bank transfer
Payment method: account 02230017345 at bank JPMorgan Chase

If you liked this article and found it informative regarding F# functional programming language, you can leave your feedback by reacting below.

We value your feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Subscribe To Our Newsletter
Enter your email to receive a weekly round-up of our best posts. Learn more!
icon

Leave a Reply

Your email address will not be published. Required fields are marked *