Discriminated Unions and Union types represent for the first time since the beginning of the chapter constructs not necessarily related to functional programming. They are essential to simplify the development of libraries and applications in F#.
The Record type is a set of simple values that are named and can optionally have members.
Their syntax is as follows:
[ attributes ] type [accessibility-modifier] typename = { [ mutable ] label1 : type1; [ mutable ] label2 : type2; ... } member-list
Take a look at the following example:
//Record Type type Point = { x : float; y: float; z: float option; } let point2D = { x = 1.0; y = 1.0; z = None} let point3D = { point2D with z = Some(-1.0)}
In this example, you can see some of the syntactic features of the Record type.
The keyword option declared during the type definition indicates that value can be inserted or not. None
and Some (<value>)
are used precisely to indicate in the first variable not assigned a value and in the second such award, respectively.
The keyword with
preceded by an identifier already valued permits passing all the values of the first variable to the declaration of the new variable. In this way, we don't have to change the values every time, but we have the advantage to replace only the values that you want to change.
The Record type might seem like a class of C #, but in reality, there are some important differences. They are as follows:
mutable
Instead, Discriminated Unions provide support for tagged values with a label, forming a casuistic. In addition, each of them can have completely different values and types.
The syntax is as follows:
type type-name = | case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ] type2 ...] | case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
An example is as follows:
//Discriminated unions type Shape = | Rectangle of width : float * length : float | Circle of radius : float | Prism of width : float * float * height : float let rect = Rectangle(length = 1.3, width = 10.0) let circ = Circle (1.0) let prism = Prism(5., 2.0, height = 3.0)
The labelable
type can be anything. If there are no values, discriminated unions are similar to the enumeration of .NET. Instead, if there are values, each of them can be a primitive type or tuple
or just one Record type.
One particular development of discriminated unions is the possibility to insert them into another through the association with a label. These discriminated recursive unions are used to represent the tree structures.
In Microsoft Visual Studio, by creating a new F# project called Tutorial
, you can see the sample code of most language constructs.
Here, we will report a good example of Record and Discriminated Unions type. In addition, this code portion allows us to understand the concepts discussed previously with regard to the good design and conciseness of F#. Take a look at the following example:
type Suit = | Hearts | Club | Diamonds| Spades // Represents the rank of a playing card type Rank = | Value of int // Represents the rank of cards 2 .. 10 | Ace | King | Queen | Jack static member GetAllRanks() = [ yield Ace for i in 2 .. 10 do yield Value i yield Jack yield Queen yield King ] type Card = { Suit: Suit; Rank: Rank } // Returns a list representing all the cards in the deck let fullDeck = [ for suit in [ Hearts; Diamonds; Clubs; Spades] do for rank in Rank.GetAllRanks() do yield { Suit=suit; Rank=rank } ]
3.145.101.81