Introduction to Discrimnated Unions
Introduction to Discrimnated Unions
Fundamentals of Discrimnated Unions
Introduction
A union is an object made of different parts but only one of those parts must be validated or considered in a particular program. This means that, unlike a class where all of the members of the object are available any time, when a union is used, only one of its members must be selected and used. For this reason, it is called a discriminated union.
Creating a Union
The primary formula to create a discriminated union is:
type union-name = ...
You start with the required type keyword. The name of the union, union-name, follows the rules of names of classes. After the name of the union, type =
The body of a Union
The body of a union is the section after its = symbol.
Adding a Member to a Union
A union contains one or more members. The simplest union has only one member. To add such a member, in the body of the union, that is, after the equal symbol, type | followed by the name of the member. The names of members follow the rules of names of classes. Here is an example:
type School = | Student
As you can see, a discriminted union starts the same as an enumeration (in fact, you can define a union like the above example and stop there, which would make it similar to an enumeration). The difference is that you usually create a union because you want its member to have a particular meaningful behavior. As a result, a member of a union should have meaning; such a member can be a complete object. This means that a member of a discrimnated union can consist of one internal value or many values. If a member has one value, specify the data type of that member, follow its name by the of keyword followed by a known type. Here are examples:
type School = | Student of string
To define what the discrimnated union member does, create a pattern matching expression in which the union member has a case. In the case section of a member, create a name like a variable and use it. At a minimum, you can simply return that name using the -> operator. This can be done as follows:
type School = | Student of string
let describe studies = match studies with | Student fullName -> fullName
Using a Discriminated Union
To use a discriminated union, you can declare a variable and assign the matching case as if it were a constructor to which you pass a value. To show the value of a case, use %A in its placeholder of the printf of the printfn function. Here is an example:
type School = | Student of string
let describe studies = match studies with | Student fullName -> fullName
let std = Student("Yamaguchi")
printfn "%A" std
This would produce:
Student "Yamaguchi" Press any key to close this window . . .
A Union with many Members
The Members of a Union
Although we introduced unions with only one member, a typical union has more than one member. Such members a primarilly created as we saw for an enumeration. Here are examples:
type School =
| Student
| Course
| Building
One of the primary differences between an enumeration and a discriminted union is that you usually create a union because you want each member to have a particular meaning. As each member of a union should have meaning, such a member can be a complete object. As a result, the updated formula to create a discriminated union is:
type union-name = | case-name-1 [of [ field1 : ] type1 [ * [ field2 : ] type2 . . .type_x ] | case-name-2 [of [ field3 : ] type3 [ * [ field4 : ] type4 . . .type_y ] | case-name_n [of [ field_n : ] type_n [ * [ field_n : ] type_n . . .type_z ]
Based on this, start the creation of a member as a case of a matching pattern; that is, a | symbol followed by a name. A member of a discrimnated union can consist of one internal value or many values. If a member has one value, specify the data type of that member. To do this, follow the name of the member with the of keyword followed by a known type. Here are examples:
type School = | Student of string | Course of string | Building of string
To define what the discrimnated union members do, create a pattern matching expression in which each union member has a case. In the case section of a member, create a name like a variable and use it. At a minimum, you can simply return that name using the -> operator. This can be done as follows:
let describe studies =
match studies with
| Student fullName -> fullName
| Course code -> code
| RoomNumber room -> room
Using a Discriminated Union
To use a discriminated union, you can declare a variable and assign the matching case as if it were a constructor to which you pass a value. To show the value of a case, use %A in its placeholder of the printf of the printfn function. Here are examples:
type School = | Student of string | Course of string | Room of string let describe studies = match studies with | Student fullName -> fullName | Course code -> code | Room nbr -> nbr let std = Student("Yamaguchi") printfn "%A" std let crs = Course("Introduction to Web Design") printfn "%A" crs let rm = Room("Science and Aircraft") printfn "%A" rm;
This would produce:
Student "Yamaguchi" Course "Introduction to Web Design" Room "Science and Aircraft" Press any key to close this window . . .
You can also first declare a variable for each value and pass that variable to the case. Here are examples:
type School = | Student of string | Course of string | Room of string let describe studies = match studies with | Student fullName -> fullName | Course code -> code | Room nbr -> nbr let name = "Yamaguchi" let std = Student(name) printfn "%A" std let study = "Introduction to Web Design" let crs = Course(study) printfn "%A" crs let building = "Science and Aircraft" let rm = Room(building) printfn "%A" rm
Although we used only one value for each, a member of a union can use many internal values. To indicate that a member is made of more than one value, add * and the data type of that member. Here are examples:
type School = | Student of string * char * string | Course of string * int | Room of string * string
To specify the composition of a member, pass the appropriate arguments to its name, the way you would do as if it was a constructor. Outside of the parentheses, type -> followed by the expression that constitutes the value of the member. Here are examples:
let describe studies = match studies with | Student (f, m, l) -> f + " " + (string m) + ". " + l | Course (code, credit) -> code + (string credit) | Room (building, nbr) -> building + " " + nbr
To use a member, pass the appropriate values to its constructor and assign it to the desired variable. Here are examples:
type School = | Student of string * char * string | Course of string * int | Room of string * string let describe studies = match studies with | Student (f, m, l) -> f + " " + (string m) + ". " + l | Course (code, credit) -> code + (string credit) | Room (building, nbr) -> building + " " + nbr let firstName = "Paul" let lastName = "Yamaguchi" let middleInitial = 'B' let std = Student(firstName, middleInitial, lastName) printfn "%A" std let study = "Introduction to Web Design" let crd = 3; let crs = Course(study, crd) printfn "%A" crs let building = "Science and Aircraft" let rmNbr = "A104" let rm = Room(building, rmNbr) printfn "%A" rm
This would produce:
Student ("Paul",'B',"Yamaguchi") Course ("Introduction to Web Design",3) Room ("Science and Aircraft","A104") Press any key to close this window . . .
Built-In Discriminated Unions
Optional Arguments in a Function
A parameter is referred to as optional if a function can use it or not. For example, when you call a function, you can specify the value(s) of the parameter(s) or omit it (them). This means that, by default, all function parameters in F# are optional. Still, when you are creating a function, you can indicate that the caller will have the ability to pass or omit an argument.
To specify that a parameter is optional, first add the parentheses to the function. In the parentheses, type the name of the parameter, followed by a colon and its data type, followed by option. Here is an example:
let getMembership (c : int option) =
. . .
You can then use the argument in the function or not. Here is an example:
let getMembership (c : int option) =
printfn "Public Library Acknowledgement: %A" c
A Generic Discriminated Union
When you call a function, the F# language allows you to find out whether an argument was passed or not. To assist you with this, the F# language provides a generic discriminated union named Option. It is defined as follows:
type Option<'a> = | Some of 'a | None
The Option union, which is also used as option, has two members: Some and None. The formula to use it is:
match Value with | Some Value -> Some Statement | None -> None Statement
The Some member is used to validate or acknowledge that an argument, represented here by Value, was passed to the function. If no argument was passed, the None member is valid. After each option, type -> followed by what you want to do. Here is an example:
let getMembership (c : int option) =
match c with
| Some c -> "Valid Membership"
| None -> "Unknown Category";
When calling the function, you can omit the argument if you want, in which case the function would not treat it. Here is an example:
let getMembership (c : int option) =
match c with
| Some c -> "Valid Membership"
| None -> "Unknown Category"
let result = getMembership
printfn "Library Membership Category: %A" result;
If you want to pass the argument, preceded its value by the Some word. Here is an example:
let getMembership (c : int option) =
match c with
| Some c -> "Valid Membership"
| None -> "Unknown Category"
let result = getMembership (Some 2)
printfn "Library Membership Category: %A" result;
This would produce:
Library Membership Category: "Valid Membership" Press any key to close this window . . .
In the same way, in the Some section, now that you know an argument was passed, you can process it as you see fit. Here is an example:
let getMembership (c : int option) =
match c with
| Some c ->
if c = 1 then "Teen"
elif c = 2 then "Adult"
elif c = 3 then "Senior"
else "Invalid Category"
| None -> "Empty";
let result = getMembership (Some 2)
printfn "Library Membership Category: %s" result;
This would produce:
Library Membership Category: Adult Press any key to close this window . . .
Of course, you can use pattern matching in the Some section if you want. Here is an example:
let getMembership (c : int option) =
match c with
| Some c ->
match c with
| 1 -> "Teen"
| 2 -> "Adult"
| 3 -> "Senior"
| _ -> "Invalid Category"
| None -> "Empty";
let result = getMembership (Some 1)
printfn "Library Membership Category: %s" result;
This would produce:
Library Membership Category: Teen Press any key to close this window . . .
|
|||
Previous | Copyright © 2014-2024, FunctionX | Tuesday 31 October 2023 | Next |
|