Home

F# Topics: Enumerations

 

Fundamentals of Functions

 

Introduction

Imagine you have a few constant natural numbers (such as 1, 4, 10, and 42) and you want to use them in you code. Sometimes you use such numbers to perform comparisons. On paper, those numbers would mean different things to different people. Instead of using such numbers, you can name them and use the names. An enumeration is a technique of creating names to be used in place of constant numbers.

Creating an Enumeration

An enumeration is created with the type keyword, a name, the = sign and one or a list of members. Each member is in the form | followed by a name. The primary formula to create an enumeration is:

type EnumerationName = | MemberName1 | MemberName2 | MemberName_n

Alternatively, each member of the enumeration can be written on its own line:

type EnumerationName =
| MemberName1
| MemberName2
| MemberName_n

The name of an enumeration usually starts with an uppercase letter. The = sign precedes the body of the enumeration. Here are two examples:

type TimeZoneInclusion = | Entirely | Split

type InterestCompounded =
| Daily
| Weekly
| Monthly
| Quarterly
| Semiannually
| Annually

If the members are created on separate lines, if you want, you can indent them, but this is only an option.

Enumerations and Variables

You can declare a variable that is based on an enumeration. As done with the other types, you don't have to specify the type of the variable. To indicate that the variable is bound to an enumeration, initialize the variable using a member of the enumeration. Here is an example:

type Compound =
    | Daily
    | Weekly
    | Monthly
    | Quarterly
    | Semiannually
    | Annually
    
let compounding = Monthly

To add a member of an enumeration in sprintf, use %A in the placeholder.

Enumerations and Conditional Statements

You can access any member of the enumeration in your code. This can be done in a conditional statement where you would compare your variable to members of the enumeration. Here are example:

open System
open System.Windows.Forms

type Compound =
| Daily
| Weekly
| Monthly
| Quarterly
| Semiannually
| Annually

let mutable compounding = Monthly

let compoundInterest = new Form()
compoundInterest.Text   <- "Compound Interest"
compoundInterest.Width  <- 300
compoundInterest.Height <- 228

let lblPrincipal = new Label()
lblPrincipal.Left  <- 18
lblPrincipal.Top   <- 18
lblPrincipal.Width <- 62
lblPrincipal.Text  <- "Principal:"
compoundInterest.Controls.Add(lblPrincipal)

let txtPrincipal = new TextBox()
txtPrincipal.Left  <- 105
txtPrincipal.Top   <- 16
txtPrincipal.Width <- 84
txtPrincipal.Text  <- "0.00"
compoundInterest.Controls.Add(txtPrincipal)

let lblInterestRate = new Label()
lblInterestRate.Left  <- 18
lblInterestRate.Top   <- 46
lblInterestRate.Width <- 80
lblInterestRate.Text  <- "Interest Rate:"
compoundInterest.Controls.Add(lblInterestRate)

let txtInterestRate = new TextBox()
txtInterestRate.Left  <-  105
txtInterestRate.Top   <- 44
txtInterestRate.Width <-  60
txtInterestRate.Text  <- "0.00"
compoundInterest.Controls.Add(txtInterestRate)

let lblPercent = new Label()
lblPercent.Left  <- 165
lblPercent.Top   <- 46
lblPercent.Width <- 22
lblPercent.Text  <- "%"
compoundInterest.Controls.Add(lblPercent)

let lblPeriods = new Label()
lblPeriods.Left  <- 18
lblPeriods.Top   <- 76
lblPeriods.Width <- 62
lblPeriods.Text  <- "Periods:"
compoundInterest.Controls.Add(lblPeriods)

let txtPeriods = new TextBox()
txtPeriods.Left  <- 105
txtPeriods.Top   <- 73
txtPeriods.Width <- 60
txtPeriods.Text  <- "0"
compoundInterest.Controls.Add(txtPeriods)

let lblYears = new Label()
lblYears.Left  <- 165
lblYears.Top   <- 76
lblYears.Text  <- "Years"
compoundInterest.Controls.Add(lblYears)

let lblCompounded = new Label()
lblCompounded.Left  <- 18
lblCompounded.Top   <- 106
lblCompounded.Width <- 80
lblCompounded.Text  <- "Compounded:"
compoundInterest.Controls.Add(lblCompounded)

let cbxCompounded = new ComboBox()
cbxCompounded.Left  <- 105
cbxCompounded.Top   <- 101
cbxCompounded.Width <- 84
cbxCompounded.Items.AddRange([| "Daily"; "Weekly"; "Monthly"; "Quarterly"; "Semiannually"; "Annually" |])
cbxCompounded.Text  <- "Annually"

let btnCalculate = new Button()
btnCalculate.Left  <- 196
btnCalculate.Top   <- 102
btnCalculate.Text  <- "Calculate"

let lblInterestEarned = new Label()
lblInterestEarned.Left  <- 18
lblInterestEarned.Top   <- 135
lblInterestEarned.Width <- 85
lblInterestEarned.Text  <- "Interest Earned:"
compoundInterest.Controls.Add(lblInterestEarned)

let txtInterestEarned = new TextBox()
txtInterestEarned.Left  <- 105
txtInterestEarned.Top   <- 132
txtInterestEarned.Width <- 84
txtInterestEarned.Text  <- "0.00"
compoundInterest.Controls.Add(txtInterestEarned)

let lblFutureValue = new Label()
lblFutureValue.Left  <- 18
lblFutureValue.Top   <- 160
lblFutureValue.Width <- 80
lblFutureValue.Text  <- "Future Value:"
compoundInterest.Controls.Add(lblFutureValue)

let txtFutureValue = new TextBox()
txtFutureValue.Left  <- 105
txtFutureValue.Top   <- 160
txtFutureValue.Width <- 84
txtFutureValue.Text  <- "0.00"
compoundInterest.Controls.Add(txtFutureValue)

let btnClose = new Button()
btnClose.Left  <- 196
btnClose.Top   <- 156
btnClose.Width <-  75
btnClose.Text  <- "Close"

let cbxCompoundedSelectedIndexChanged(e) =
    if cbxCompounded.Text = "Daily" then
        compounding <- Daily
    elif cbxCompounded.Text = "Weekly" then
        compounding <- Weekly
    elif cbxCompounded.Text = "Monthly" then
        compounding <- Monthly
    elif cbxCompounded.Text = "Quarterly" then
        compounding <- Quarterly
    elif cbxCompounded.Text = "Semiannually" then
        compounding <- Semiannually
    else // if(cbxCompounded.Text = "Annually")
        compounding <- Annually

cbxCompounded.SelectedIndexChanged.Add(cbxCompoundedSelectedIndexChanged)
compoundInterest.Controls.Add(cbxCompounded)

let btnCalculateClick(e) =
    let mutable compoundFrequency = 0.00
    let principal = float txtPrincipal.Text
    let interestRate = (float txtInterestRate.Text) / 100.00
    let periods = float txtPeriods.Text

    if compounding = Daily then
        compoundFrequency <- 365.00
    elif compounding = Weekly then
        compoundFrequency <- 52.00
    elif compounding = Monthly then
        compoundFrequency <- 12.00
    elif compounding = Quarterly then
        compoundFrequency <- 4.00
    elif compounding = Semiannually then
        compoundFrequency <- 2.00
    else // if compounding = Annually then
        compoundFrequency <- 1.00

    let futureValue = principal * ((1.00 + (interestRate / compoundFrequency)) ** compoundFrequency * periods)
    let interestEarned = futureValue - principal
    
    txtInterestEarned.Text <- (sprintf "%0.02f" interestEarned)
    txtFutureValue.Text <- (sprintf "%0.02f" futureValue)
btnCalculate.Click.Add(btnCalculateClick)
compoundInterest.Controls.Add(btnCalculate)

let btnCloseClick(e) = compoundInterest.Close()
btnClose.Click.Add(btnCloseClick)
compoundInterest.Controls.Add(btnClose)

Application.Run(compoundInterest)

Here is an example of running the program:

Enumerations and Conditional Statements

Enumerations and Conditional Statements

Remember that you can specify the data type of a variable by following its name with a colon and the data type. This can be done as follows for an enumeration:

type Compound =
| Daily
| Weekly
| Monthly
| Quarterly
| Semiannually
| Annually

let compounding : Compound = Monthly

Furthermore, to refer to a member of an enumeration and to make your code easier to read, you can qualify each member of an enumeration. This is done by preceding the name of the member of the enumeration with the name of the enumeration separated by a period. Here are examples:

let cbxCompoundedSelectedIndexChanged(e) =
    if cbxCompounded.Text = "Daily" then
        compounding <- Compound.Daily
    elif cbxCompounded.Text = "Weekly" then
        compounding <- Compound.Weekly
    elif cbxCompounded.Text = "Monthly" then
        compounding <- Compound.Monthly
    elif cbxCompounded.Text = "Quarterly" then
        compounding <- Compound.Quarterly
    elif cbxCompounded.Text = "Semiannually" then
        compounding <- Compound.Semiannually
    else
        compounding <- Compound.Annually

cbxCompounded.SelectedIndexChanged.Add(cbxCompoundedSelectedIndexChanged)
compoundInterest.Controls.Add(cbxCompounded)

let btnCalculateClick(e) =
    let mutable compoundFrequency = 0.00
    let principal = float txtPrincipal.Text
    let interestRate = (float txtInterestRate.Text) / 100.00
    let periods = float txtPeriods.Text

    if compounding = Compound.Daily then
        compoundFrequency <- 365.00
    elif compounding = Compound.Weekly then
        compoundFrequency <- 52.00
    elif compounding = Compound.Monthly then
        compoundFrequency <- 12.00
    elif compounding = Compound.Quarterly then
        compoundFrequency <- 4.00
    elif compounding = Compound.Semiannually then
        compoundFrequency <- 2.00
    else // if compounding = Compound.Annually then
        compoundFrequency <- 1.00

    let futureValue = principal * ((1.00 + (interestRate / compoundFrequency)) ** compoundFrequency * periods)
    let interestEarned = futureValue - principal
    
    txtInterestEarned.Text <- (sprintf "%0.02f" interestEarned)
    txtFutureValue.Text <- (sprintf "%0.02f" futureValue)
     
 

The Values of Members of an Enumeration

An enumeration contains members whose names actually represent constant values. The numeric values can be anything you want. In fact, you can specify the value of each member as you want. To do this, assign the desired number to each member of the enumeration. The formulat to use is:

type EnumerationName =
    | MemberName1 [ = IntegralValue1 ]
    | MemberName2 [ = IntegralValue2 ] ]
    | MemberName_n [ = IntegralValue_n ]

As you saw in the beginning, you don't have to specify the values of the members of an enumeration; but unlike other languages such as C/C++ or C#, if you decide to give values, you must assign a number to each member of the enumeration. Here are examples:

type Category =
    | Teen = 10
    | Adult = 20
    | Senior = 30

As you saw in the beginning, you don't have to specify the values of the members of an enumeration; but unlike other languages such as C/C++ or C#, if you decide to give values, you must assign a number to each member of the enumeration. After specifying the values of members of the enumeration, whenever you want to use a member of that enumeration in your code, you must qualify that member. Here are examples:

open System
open System.Windows.Forms

type Compound =
| Daily = 365
| Weekly = 52
| Monthly = 12
| Quarterly = 4
| Semiannually = 2
| Annually = 1

let mutable compounding = Compound.Monthly

let compoundInterest = new Form()
compoundInterest.Text   <- "Compound Interest"
compoundInterest.Width  <- 300
compoundInterest.Height <- 228

let lblPrincipal = new Label()
lblPrincipal.Left  <- 18
lblPrincipal.Top   <- 18
lblPrincipal.Width <- 62
lblPrincipal.Text  <- "Principal:"
compoundInterest.Controls.Add(lblPrincipal)

let txtPrincipal = new TextBox()
txtPrincipal.Left  <- 105
txtPrincipal.Top   <- 16
txtPrincipal.Width <- 84
txtPrincipal.Text  <- "0.00"
compoundInterest.Controls.Add(txtPrincipal)

let lblInterestRate = new Label()
lblInterestRate.Left  <- 18
lblInterestRate.Top   <- 46
lblInterestRate.Width <- 80
lblInterestRate.Text  <- "Interest Rate:"
compoundInterest.Controls.Add(lblInterestRate)

let txtInterestRate = new TextBox()
txtInterestRate.Left  <-  105
txtInterestRate.Top   <- 44
txtInterestRate.Width <-  60
txtInterestRate.Text  <- "0.00"
compoundInterest.Controls.Add(txtInterestRate)

let lblPercent = new Label()
lblPercent.Left  <- 165
lblPercent.Top   <- 46
lblPercent.Width <- 22
lblPercent.Text  <- "%"
compoundInterest.Controls.Add(lblPercent)

let lblPeriods = new Label()
lblPeriods.Left  <- 18
lblPeriods.Top   <- 76
lblPeriods.Width <- 62
lblPeriods.Text  <- "Periods:"
compoundInterest.Controls.Add(lblPeriods)

let txtPeriods = new TextBox()
txtPeriods.Left  <- 105
txtPeriods.Top   <- 73
txtPeriods.Width <- 60
txtPeriods.Text  <- "0"
compoundInterest.Controls.Add(txtPeriods)

let lblYears = new Label()
lblYears.Left  <- 165
lblYears.Top   <- 76
lblYears.Text  <- "Years"
compoundInterest.Controls.Add(lblYears)

let lblCompounded = new Label()
lblCompounded.Left  <- 18
lblCompounded.Top   <- 106
lblCompounded.Width <- 80
lblCompounded.Text  <- "Compounded:"
compoundInterest.Controls.Add(lblCompounded)

let cbxCompounded = new ComboBox()
cbxCompounded.Left  <- 105
cbxCompounded.Top   <- 101
cbxCompounded.Width <- 84
cbxCompounded.Items.AddRange([| "Daily"; "Weekly"; "Monthly"; "Quarterly"; "Semiannually"; "Annually" |])
cbxCompounded.Text  <- "Annually"

let btnCalculate = new Button()
btnCalculate.Left  <- 196
btnCalculate.Top   <- 100
btnCalculate.Text  <- "Calculate"

let lblInterestEarned = new Label()
lblInterestEarned.Left  <- 18
lblInterestEarned.Top   <- 135
lblInterestEarned.Width <- 85
lblInterestEarned.Text  <- "Interest Earned:"
compoundInterest.Controls.Add(lblInterestEarned)

let txtInterestEarned = new TextBox()
txtInterestEarned.Left  <- 105
txtInterestEarned.Top   <- 132
txtInterestEarned.Width <- 84
txtInterestEarned.Text  <- "0.00"
compoundInterest.Controls.Add(txtInterestEarned)

let lblFutureValue = new Label()
lblFutureValue.Left  <- 18
lblFutureValue.Top   <- 160
lblFutureValue.Width <- 80
lblFutureValue.Text  <- "Future Value:"
compoundInterest.Controls.Add(lblFutureValue)

let txtFutureValue = new TextBox()
txtFutureValue.Left  <- 105
txtFutureValue.Top   <- 160
txtFutureValue.Width <- 84
txtFutureValue.Text  <- "0.00"
compoundInterest.Controls.Add(txtFutureValue)

let btnClose = new Button()
btnClose.Left  <- 196
btnClose.Top   <- 158
btnClose.Width <-  75
btnClose.Text  <- "Close"

let cbxCompoundedSelectedIndexChanged(e) =
    if cbxCompounded.Text = "Daily" then
        compounding <- Compound.Daily
    elif cbxCompounded.Text = "Weekly" then
        compounding <- Compound.Weekly
    elif cbxCompounded.Text = "Monthly" then
        compounding <- Compound.Monthly
    elif cbxCompounded.Text = "Quarterly" then
        compounding <- Compound.Quarterly
    elif cbxCompounded.Text = "Semiannually" then
        compounding <- Compound.Semiannually
    else // if(cbxCompounded.Text = "Annually")
        compounding <- Compound.Annually

cbxCompounded.SelectedIndexChanged.Add(cbxCompoundedSelectedIndexChanged)
compoundInterest.Controls.Add(cbxCompounded)

let btnCalculateClick(e) =
    let mutable compoundFrequency = 0.00
    let principal = float txtPrincipal.Text
    let interestRate = (float txtInterestRate.Text) / 100.00
    let periods = float txtPeriods.Text

    if compounding = Compound.Daily then
        compoundFrequency <- 365.00
    elif compounding = Compound.Weekly then
        compoundFrequency <- 52.00
    elif compounding = Compound.Monthly then
        compoundFrequency <- 12.00
    elif compounding = Compound.Quarterly then
        compoundFrequency <- 4.00
    elif compounding = Compound.Semiannually then
        compoundFrequency <- 2.00
    else // if compounding = Annually then
        compoundFrequency <- 1.00

    let futureValue = principal * ((1.00 + (interestRate / compoundFrequency)) ** compoundFrequency * periods)
    let interestEarned = futureValue - principal
    
    txtInterestEarned.Text <- (sprintf "%0.02f" interestEarned)
    txtFutureValue.Text <- (sprintf "%0.02f" futureValue)
btnCalculate.Click.Add(btnCalculateClick)
compoundInterest.Controls.Add(btnCalculate)

let btnCloseClick(e) = compoundInterest.Close()
btnClose.Click.Add(btnCloseClick)
compoundInterest.Controls.Add(btnClose)

Application.Run(compoundInterest)

Remember that you can assign any value you want to each member of the enumeration but the values must be integers or characters of type sbyte, byte, int16, uint16, int32, uint32, int64, uint16, uint64, or char.

Functions and Enumerations

 

Returning an Enumeration

Just like an enumeration can be used as a data type for variables, it can be involved with functions. To return an enumeration from a function, when creating the function, specify its return type with the name of the enumeratio. In the body of the function, make sure the last statement indicates that the function is returning the value of an enumeration. Here is an example:

type TriangleType =
| Right
| Equilateral
| Isosceles
| Obtuse
| Acute

let getTypeOfTriangle() : TriangleType =
    Equilateral

You can then get the returned value of the function and use it as you see fit. Here is a simple example that displays the return value of a function:

open System
open System.Windows.Forms

type TriangleType =
| Right
| Equilateral
| Isosceles
| Obtuse
| Acute

let getTypeOfTriangle() : TriangleType =
    Equilateral

// Form: Geometric Triangle
let geometricTriangle : Form = new Form()
geometricTriangle.Width  <- 265
geometricTriangle.Height <- 138
geometricTriangle.Text <- "Triangle"

// Label: Type of Triangle
let lblTypeOfTriangle : Label = new Label()
lblTypeOfTriangle.Left   <- 22
lblTypeOfTriangle.Top    <- 19
lblTypeOfTriangle.Width  <- 80
lblTypeOfTriangle.Text   <- "Triangle Type:"
geometricTriangle.Controls.Add lblTypeOfTriangle

// Text Box: Type of Triangle
let txtTypeOfTriangle : TextBox = new TextBox()
txtTypeOfTriangle.Left  <- 102
txtTypeOfTriangle.Top   <- 16
txtTypeOfTriangle.Width <- 64
geometricTriangle.Controls.Add txtTypeOfTriangle

let result = getTypeOfTriangle()

txtTypeOfTriangle.Text <- sprintf "%A" result
    
Application.Run geometricTriangle

This would produce:

Enumerations and Functions

Passing an Enumeration

On the other hand, if you are passing an enumeration as parameter, make sure you specify the data type of the parameter. Here is an example:

open System
open System.Windows.Forms

type TriangleType =
| Right
| Equilateral
| Isosceles
| Obtuse
| Acute

// Form: Geometric Triangle
let geometricTriangle : Form = new Form()
geometricTriangle.Width  <- 225
geometricTriangle.Height <- 168
geometricTriangle.Text <- "Triangle"

let getSummary (b : float) (h : float) (t : TriangleType) =
    let area = b * h / 2.00
    sprintf "%f (%A)" area t

// Label: Base
let lblBase : Label = new Label()
lblBase.Left   <- 22
lblBase.Top    <- 19
lblBase.Width  <- 40
lblBase.Text   <- "Base:"
geometricTriangle.Controls.Add lblBase

// Text Box: Base
let txtBase : TextBox = new TextBox()
txtBase.Left  <- 82
txtBase.Top   <- 16
txtBase.Width <- 54
txtBase.Text  <- "36.84"
geometricTriangle.Controls.Add txtBase

// Label: Height
let lblHeight : Label = new Label()
lblHeight.Left  <- 22
lblHeight.Top   <- 50
lblHeight.Width <- 45
lblHeight.Text  <- "Height:"
geometricTriangle.Controls.Add lblHeight

// Text Box: Height
let txtHeight : TextBox = new TextBox()
txtHeight.Left  <- 82
txtHeight.Top   <- 43
txtHeight.Width <- 54
txtHeight.Text  <- "26.74"
geometricTriangle.Controls.Add txtHeight

// Label: Summary
let lblSummary : Label = new Label()
lblSummary.Left  <-  22
lblSummary.Top   <- 78
lblSummary.Width <-  60
lblSummary.Text  <- "Summary:"
geometricTriangle.Controls.Add lblSummary

// Text Box: Summary
let txtSummary : TextBox = new TextBox()
txtSummary.Left  <- 82
txtSummary.Top   <- 75
txtSummary.Width <- 122
geometricTriangle.Controls.Add txtSummary

// Button: Close
let btnClose : Button = new Button()
btnClose.Left <- 22
btnClose.Top  <- 105
btnClose.Width  <- 182
btnClose.Text <- "Close"
let btnCloseClick e = geometricTriangle.Close()
btnClose.Click.Add btnCloseClick
geometricTriangle.Controls.Add btnClose

let x = float txtBase.Text
let y = float txtHeight.Text

let summary = getSummary x y Isosceles
txtSummary.Text <- summary

Application.Run geometricTriangle

This would produce:

Enumerations and Functions

   
   
 

Previous Copyright © 2015, FunctionX Next