Home

Introduction

 

Fundamentals

 

Introduction

 

 

     
 
 

 

   
   
 

Previous Copyright © 2015 FunctionX Next

Home

Pattern Matching

 

Matching an Item from a Pattern

 

Introduction

Pattern matching consists of comparing many values, one at a time, to a constant one, to find one that matches the constant.

To perform pattern matching, you use the match operator. There are various ways to use it. The primary formula to follow is:

match SomeValue with
| value1 -> What-to-Do
| value2 -> What-to-Do

You start with the match keyword. SomeValue must be recognized as having a value. SomeValue can be a local variable declared and initialized before the match expression.

In the body of the match expression, start each option with the pipe operator "|".  This operator is followed by the value (value1, value2, etc) to compare to SomeValue. This is followed by ->. If the value (for example value1) matches SomeValue, you must perform an action. If the value doesn't match SomeValue, that option is ignored and the comparison is performed on the next value. This continues until a value matches SomeValue.

SomeValue can come from an argument passed to a function where it is being used.

As we will see, pattern matching can be done using various types of values, such as members of an enumeration. In this case, each value must be a member of the enumeration. Here is an example:

open System
open System.Windows.Forms

type Courselevel =
| Beginning
| Intermediate
| Advanced

let choice : Courselevel = Intermediate
let mutable availableCourses : string = ""

let computerTrainingSchool = new Form()
computerTrainingSchool.Width  <- 350
computerTrainingSchool.Height <- 140
computerTrainingSchool.Text   <- "Computer Training School"

match choice with
| Beginning -> availableCourses <- "Introduction to Keyboarding\nIntroduction to Graphic Design\nIntroduction to Computer Databases"
| Intermediate -> availableCourses <- "Marketing with New Technologies\nIntermediate and Graphic Presentations\nRunning and Growing a Small Business\nIntermediate Keyboarding"
| Advanced -> availableCourses <- "Databases Distribution and Maintenance\nAdvanced Graphic Design and Production"

// Label: Level Selected
let lblLevelSelected = new Label()
lblLevelSelected.Left   <- 12
lblLevelSelected.Top    <- 18
lblLevelSelected.Width  <- 102
lblLevelSelected.Text   <- "Level Selected:"
computerTrainingSchool.Controls.Add(lblLevelSelected)

// Label: Level Applied
let lblLevelApplied = new Label()
lblLevelApplied.Left   <- 120
lblLevelApplied.Top    <- 18
lblLevelApplied.Width  <- 140
lblLevelApplied.Text   <- sprintf "%A" choice
computerTrainingSchool.Controls.Add(lblLevelApplied)

// Label: Available Courses
let lblAvailableCourses = new Label();
lblAvailableCourses.Left   <-  12
lblAvailableCourses.Top    <-  40
lblAvailableCourses.Width  <- 110
lblAvailableCourses.Text   <- "Available Courses:"
computerTrainingSchool.Controls.Add(lblAvailableCourses)

// Label: Courses List
let lblCoursesList = new Label();
lblCoursesList.Left   <- 120;
lblCoursesList.Top    <-  40;
lblCoursesList.Width  <- 250;
lblCoursesList.Height <- 160;
lblCoursesList.Text   <- availableCourses;
computerTrainingSchool.Controls.Add(lblCoursesList);

Application.Run(computerTrainingSchool)

This would produce:

Matching an Item from a Pattern

If There is no Match

In pattern matching, each value (value1, value2, etc) is compared to SomeValue. In some cases, no value will match. You should indicate what to do when this happens. To indicate that there was no match, you can specify the last option with the underscore wildcard, then indicate what to do in that case. The underscore wildcard means anything (or any value) that is not one of those specified. Here is an example of using the underscore wildcard:

Author Note

In this example, customers deposit money in bank account (savings account). We will calculate how much money they will earn based on the interest rate. The bank (or this application) specifies the interest rate based on the frequency of compounding (daily, monthly, quarterly, or annually.

open System
open System.Windows.Forms

let mutable interestRate = 0.00

// Compound Interest
let compoundInterest = new Form()
compoundInterest.Width  <- 305
compoundInterest.Height <- 235
compoundInterest.Text   <- "Compound Interest"

// Label: Principal
let lblPrincipal = new Label()
lblPrincipal.Left <- 12
lblPrincipal.Top  <- 21
lblPrincipal.Text <- "Amount Deposited:"
compoundInterest.Controls.Add(lblPrincipal)

// Text Box: Principal
let txtPrincipal = new TextBox()
txtPrincipal.Left  <- 115
txtPrincipal.Top   <-  18
txtPrincipal.Width <-  64
txtPrincipal.Text  <- "0.00"
compoundInterest.Controls.Add(txtPrincipal)

// Label: Periods
let lblPeriods = new Label()
lblPeriods.Left <- 12
lblPeriods.Top <- 50
lblPeriods.Text <- "Periods:"
compoundInterest.Controls.Add(lblPeriods)

// Text Box: Periods
let txtPeriods = new TextBox()
txtPeriods.Left  <- 115
txtPeriods.Top   <-  47
txtPeriods.Width <-  45
txtPeriods.Text  <- "0"
compoundInterest.Controls.Add(txtPeriods)

// Label: Years
let lblYears = new Label()
lblYears.Left <- 166
lblYears.Top  <-  50
lblYears.Text <- "Years"
compoundInterest.Controls.Add(lblYears)

// Label: Compounded
let lblCompounded = new Label()
lblCompounded.Left <- 12
lblCompounded.Top  <- 79
lblCompounded.Text <- "Compounded:"
compoundInterest.Controls.Add(lblCompounded)

// Combo Box: Compounded
let cbxCompounded = new ComboBox()
cbxCompounded.Left  <- 115
cbxCompounded.Top   <-  76
cbxCompounded.Width <- 166
cbxCompounded.Items.AddRange [| "Daily"; "Monthly"; "Quarterly"; "Yearly" |]
compoundInterest.Controls.Add(cbxCompounded)

// Label: Interest Rate
let lblInterestRate = new Label()
lblInterestRate.Left <-  14
lblInterestRate.Top  <- 109
lblInterestRate.Text <- "Interest Rate:"
compoundInterest.Controls.Add(lblInterestRate)

// Text Box: Interest Rate
let txtInterestRate = new TextBox()
txtInterestRate.Left <- 115
txtInterestRate.Top <- 106
txtInterestRate.Width <- 45
txtInterestRate.Text <- "0.00"
compoundInterest.Controls.Add(txtInterestRate)

let cbxCompoundedSelectedIndexChanged(e) =
    match cbxCompounded.SelectedIndex with
    | 0 -> interestRate <-  4.85
    | 1 -> interestRate <-  5.65
    | 2 -> interestRate <-  7.15
    | 3 -> interestRate <- 10.25
    | _ -> interestRate <- 14.50

    let strInterestRate = sprintf "%0.02f" interestRate
    txtInterestRate.Text <- strInterestRate

cbxCompounded.SelectedIndexChanged.Add(cbxCompoundedSelectedIndexChanged)

// Label: Percent
let lblPercent = new Label()
lblPercent.Left  <- 166
lblPercent.Top   <- 109
lblPercent.Width <- 40
lblPercent.Text  <- "%"
compoundInterest.Controls.Add(lblPercent)

// Button: Calculate
let btnCalculate = new Button()
btnCalculate.Left <- 206
btnCalculate.Top  <- 104
btnCalculate.Text <- "Calculate"
compoundInterest.Controls.Add(btnCalculate)

// Label: Interest Earned
let lblInterestEarned = new Label()
lblInterestEarned.Left <-  12
lblInterestEarned.Top  <- 144
lblInterestEarned.Text <- "Interest Earned:"
compoundInterest.Controls.Add(lblInterestEarned)

// Text Box: Interest Earned
let txtInterestEarned = new TextBox()
txtInterestEarned.Left <- 115
txtInterestEarned.Top <- 141
txtInterestEarned.Width <- 64
txtInterestEarned.Text <- "0.00"
compoundInterest.Controls.Add(txtInterestEarned)

// Label: Future Value
let lblFutureValue = new Label()
lblFutureValue.Left <-  12
lblFutureValue.Top  <- 171
lblFutureValue.Text <- "Future Value:"
compoundInterest.Controls.Add(lblFutureValue)

// Text Box: Future Value
let txtFutureValue = new TextBox()
txtFutureValue.Left <- 115
txtFutureValue.Top <- 169
txtFutureValue.Width <- 64
txtFutureValue.Text <- "0.00"
compoundInterest.Controls.Add(txtFutureValue)

let btnCalculateClick (e : EventArgs) =
    let mutable periods   = 0.00
    let mutable principal = 0.00

    principal <- float txtPrincipal.Text
    interestRate <- (float txtInterestRate.Text) / 100.00
    periods <- float txtPeriods.Text

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

btnCalculate.Click.Add(btnCalculateClick)

// Button: Close
let btnClose = new Button()
btnClose.Left <- 206
btnClose.Top  <-  167
btnClose.Text <- "Close"
let btnCloseClick(e) = compoundInterest. Close()
btnClose.Click.Add btnCloseClick
compoundInterest.Controls.Add btnClose   

Application.Run(compoundInterest)

Here is an example of running the program:

If There is no Match

In the same way, you can perform any simple or complex action in the wildcard section. If you don't want to take any specific action, you can specify the result with empty parentheses ().

Characteristics of Pattern Matching

 

Introduction

There are various types of values SomeValue can hold:

In our lessons, we will see other types of SomeValue.

Matching Many Disjointed Options

You can combine options that would lead to the same outcome. The options are combined using pipe operatr "|". Each is created as follows:

| Option1 | Option2 | Option_n -> Result

Of course, you can use the single option in the same match expression. Here are examples:

open System
open System.Windows.Forms 

// Form: Musical Instrument Store
let collegeAdmission : Form = new Form()
collegeAdmission.Width <- 490
collegeAdmission.Height <- 155
collegeAdmission.Text <- "College Admission"

let lblMajor               = new Label()
let cbxMajors              = new ComboBox()
let lblIntroductionCourses = new Label()
let lblAvailableCourses    = new Label()

// Label: Periods
lblMajor.Left <- 12
lblMajor.Top <- 18
lblMajor.Text <- "Major:"
collegeAdmission.Controls.Add(lblMajor)

// Combo Box: Majors
cbxMajors.Left <- 135
cbxMajors.Top <- 17
cbxMajors.Width <- 328
cbxMajors.Items.AddRange([| "English"; "History"; "Marketing"; "Accounting"; "Psychology"; "Communication Studies"; "Business Administration" |])

// Label: Introduction Courses
lblIntroductionCourses.Left <- 12
lblIntroductionCourses.Top <- 42
lblIntroductionCourses.Width <- 120
lblIntroductionCourses.Text <- "Introduction Courses:"
collegeAdmission.Controls.Add(lblIntroductionCourses)

// List Box: Introduction Courses
lblAvailableCourses.Left <- 135
lblAvailableCourses.Top <- 46
lblAvailableCourses.Width <- 348
lblAvailableCourses.Height <- 80
collegeAdmission.Controls.Add(lblAvailableCourses)

let cbxMajorsSelectedIndexChanged e =
    match cbxMajors.Text with
    | "Communication Studies" ->
        lblAvailableCourses.Text <- "HUMN 100: Introduction to Humanities(3)\n" +
                                    "SPCH 100: Foundations of Oral Communication(3)"
    | "Accounting" | "Business Administration" ->
        lblAvailableCourses.Text <- "ECON 201: Principles of Macroeconomics(3)\n" +
                                    "IFSM 201: Concepts and Applications of Information Technology(3)\n" +
                                    "WRTG 293: Introduction to Professional Writing(3)"
    | "English" | "Marketing" | "Psychology" | "History" ->
        lblAvailableCourses.Text <- "HUMN 100: Introduction to Humanities(3)\n" +
                                    "BIOL 102: Introduction to Biology(3)\n" +
                                    "WRTG 293: Introduction to Professional Writing(3)\n" +
                                    "ECON 103: Economics in the Information Age(3)\n" +
                                    "IFSM 201: Concepts and Applications of Information Technology(3)"
    | _ -> ()
collegeAdmission.Controls.Add(cbxMajors)

cbxMajors.SelectedIndexChanged.Add(cbxMajorsSelectedIndexChanged)

Application.Run collegeAdmission

This would produce:

Matching Many Disjounted Options

Matching Many Disjounted Options

Matching Many Disjounted Options

When an Additional Condition is Applied to a Case

In a matching clause, when you get to an option that matches a certain value, you can apply an additional Boolean operation before taking the desired action. The keyword to use is when. The formula to follow is:

| Option_X when condition -> What-to-do

The when condition immediately follows the option. The condition must evaluate a Boolean operation that produces a true or false value. This is equivalent to saying that if the option is value and the additional condition is true (or false), ... Based on that operation, you can then take action following the -> operator. Here are two examples:

open System
open System.Windows.Forms 

let businessLoans = new Form()
businessLoans.Width  <- 270
businessLoans.Height <- 310
businessLoans.Text   <- "Business Loan"

let lblLoanAmount = new Label()
lblLoanAmount.Left <- 21
lblLoanAmount.Top  <- 20
lblLoanAmount.Width <- 90
lblLoanAmount.Text <- "Amount of Loan:"
businessLoans.Controls.Add(lblLoanAmount)

let txtLoanAmount = new TextBox()
txtLoanAmount.Left <- 112
txtLoanAmount.Top  <- 17
txtLoanAmount.Width <- 128
txtLoanAmount.Text <- "0.00"
businessLoans.Controls.Add(txtLoanAmount)

let lblLoanType = new Label()
lblLoanType.Left <- 21
lblLoanType.Top  <- 47
lblLoanType.Width <- 73
lblLoanType.Text <- "Type of Loan:"
businessLoans.Controls.Add(lblLoanType)

let cbxLoanTypes = new ComboBox()
cbxLoanTypes.Left <- 112
cbxLoanTypes.Top  <- 44
cbxLoanTypes.Width <- 128
cbxLoanTypes.Items.AddRange([| "Car"; "Boat"; "Personal"; "Musical Instrument" |])

let lblDownPayment = new Label()
lblDownPayment.Left <- 21
lblDownPayment.Top  <- 73
lblDownPayment.Width <- 85
lblDownPayment.Text <- "Down Payment:"
businessLoans.Controls.Add(lblDownPayment)

let txtDownPaymentPercent = new TextBox()
txtDownPaymentPercent.Left <- 112
txtDownPaymentPercent.Top  <-  70
txtDownPaymentPercent.Width <- 41
txtDownPaymentPercent.Text <- "0.00"
businessLoans.Controls.Add(txtDownPaymentPercent)

let lblDownPaymentPercent = new Label()
lblDownPaymentPercent.Left <- 157
lblDownPaymentPercent.Top  <-  73
lblDownPaymentPercent.Width <- 15
lblDownPaymentPercent.Text <- "%"
businessLoans.Controls.Add(lblDownPaymentPercent)

let txtDownPaymentAmount = new TextBox()
txtDownPaymentAmount.Left <- 178
txtDownPaymentAmount.Top  <-  70
txtDownPaymentAmount.Width <- 62
txtDownPaymentAmount.Text <- "0.00"
businessLoans.Controls.Add(txtDownPaymentAmount)

let lblInterestRate = new Label()
lblInterestRate.Left <- 21
lblInterestRate.Top  <- 99
lblInterestRate.Width <- 80
lblInterestRate.Text <- "Interest Rate:"
businessLoans.Controls.Add(lblInterestRate)

let txtInterestRate = new TextBox()
txtInterestRate.Left <- 112
txtInterestRate.Top  <- 96
txtInterestRate.Width <- 41
txtInterestRate.Text <- "0.00"
businessLoans.Controls.Add(txtInterestRate)

let lblInterestRatePercent = new Label()
lblInterestRatePercent.Left <- 157
lblInterestRatePercent.Top  <- 99
lblInterestRatePercent.Width <- 15
lblInterestRatePercent.Text <- "%"
businessLoans.Controls.Add(lblInterestRatePercent)

let lblPeriods = new Label()
lblPeriods.Left  <-  21
lblPeriods.Top   <- 125
lblPeriods.Width <- 45
lblPeriods.Text  <- "Periods:"
businessLoans.Controls.Add(lblPeriods)

let txtPeriods = new TextBox()
txtPeriods.Left <- 112
txtPeriods.Top  <- 122
txtPeriods.Width <- 41
txtPeriods.Text <- "1"
businessLoans.Controls.Add(txtPeriods)

let lblYears = new Label()
lblYears.Left  <- 159
lblYears.Top   <- 125
lblYears.Width <- 34
lblYears.Text  <- "Years"
businessLoans.Controls.Add(lblYears)

let btnCalculate = new Button()
btnCalculate.Left   <-112
btnCalculate.Top    <- 148
btnCalculate.Width  <-128
btnCalculate.Height <- 32
btnCalculate.Text   <- "Calculate"

let lblInterestPaid = new Label()
lblInterestPaid.Left <-21
lblInterestPaid.Top   <- 189
lblInterestPaid.Width <- 80
lblInterestPaid.Text <- "Interest Paid:"
businessLoans.Controls.Add(lblInterestPaid)

let txtInterestPaid = new TextBox()
txtInterestPaid.Left  <- 112
txtInterestPaid.Top   <- 186
txtInterestPaid.Width <- 128
txtInterestPaid.Text  <- "0.00"
businessLoans.Controls.Add(txtInterestPaid)

let lblFutureValue = new Label()
lblFutureValue.Left  <-  21
lblFutureValue.Top   <- 215
lblFutureValue.Width <- 80
lblFutureValue.Text  <- "Future Value:"
businessLoans.Controls.Add(lblFutureValue)

let txtFutureValue = new TextBox()
txtFutureValue.Left  <- 112
txtFutureValue.Top   <- 212
txtFutureValue.Width <- 128
txtFutureValue.Text  <- "0.00"
businessLoans.Controls.Add(txtFutureValue)

let btnCalculateClick(e) =
    let loanAmount     = float txtLoanAmount.Text
    let downPaymentAmt = float txtDownPaymentAmount.Text

    let principal = loanAmount - downPaymentAmt
    let interestRate = (float txtInterestRate.Text) / 100.00
    let periods = float txtPeriods.Text

    let interestAmount = principal * periods * interestRate

    let strInterestAmount = sprintf "%0.02f" interestAmount

    txtInterestPaid.Text  <- strInterestAmount
    txtFutureValue.Text <- sprintf "%0.02f" (principal + interestAmount)

btnCalculate.Click.Add(btnCalculateClick)
businessLoans.Controls.Add(btnCalculate)

let cbxLoanTypesSelectedIndexChanged(e) =
    let mutable downPayment = 0.00
    let loanAmount = float txtLoanAmount.Text
    let mutable downPaymentRate = 10.00
    let mutable downPaymentAmt  = 10.00

    match cbxLoanTypes.Text with
    | "Car" when loanAmount >= 25000.00 -> downPaymentRate <- 20.00
    | "Boat" when loanAmount >= 35000.00 -> downPaymentRate <- 40.00
    | "Personal" when loanAmount >= 3500.00 -> downPaymentRate <- 12.50
    | "Musical Instrument" when loanAmount >= 5000.00 -> downPaymentRate <- 15.00
    | _ -> txtDownPaymentPercent.Text <- "0.00"
           txtDownPaymentAmount.Text <- "0.00"
           
    downPaymentAmt <- loanAmount * downPaymentRate / 100.00

    let strDownPaymentRate = sprintf "%0.02f" downPaymentRate
    let strDownPaymentAmt  = sprintf "%0.02f" downPaymentAmt

    txtDownPaymentPercent.Text <- strDownPaymentRate
    txtDownPaymentAmount.Text  <- strDownPaymentAmt

    txtInterestPaid.Text <- "0.00"
    txtFutureValue.Text  <- "0.00"

cbxLoanTypes.SelectedIndexChanged.Add(cbxLoanTypesSelectedIndexChanged)
businessLoans.Controls.Add(cbxLoanTypes)

let btnClose = new Button()
btnClose.Left  <- 112
btnClose.Top   <- 242
btnClose.Width <- 128
btnClose.Text  <- "Close"

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

Application.Run(businessLoans)

Here is an example of running the program:

When an Additional Condition is Applied to a Case When an Additional Condition is Applied to a Case
When an Additional Condition is Applied to a Case When an Additional Condition is Applied to a Case

The when clause is meant to state a condition. The condition can be as complex as necessary.

Options on Using Pattern Matching

 

Matching a Conditional Statement

As seen previously, you can create pattern matching that matches a Boolean value of true or false. Instead of a simple Boolean value, you can create a Boolean expression as complex as you want. For example, you can use a Boolean disjunction or conjunction.

To consider the opposite to the value to match, precede it with the not operator.

Nesting Pattern Matching

A pattern matching can be created in the body of another pattern matching. This is referred to as nesting. These are examples:

Author Note

In this example, customers deposit money in bank account (savings account). We will calculate how much money they will earn based on the interest rate. The bank (or this application) specifies the interest rate based on the frequency of compounding (daily, monthly, quarterly, or annually.

Here is an example of using the underscore wildcard:

open System
open System.Windows.Forms

(* In this example, customers deposit money in bank account (savings account).
   We will calculate how much money they will earn based on the interest rate.
   The bank (or this application) specifies the interest rate based on the 
   frequency of compounding (daily, monthly, quarterly, or annually.*)
let mutable interestRate    = 0.00
let mutable numberOfPeriods = 1.00

// Compound Interest
let compoundInterest = new Form()
compoundInterest.Width <- 285
compoundInterest.Height <- 208
compoundInterest.Text <- "Compound Interest"

// Label: Principal
let lblPrincipal = new Label()
lblPrincipal.Left <- 12
lblPrincipal.Top  <- 21
lblPrincipal.Text <- "Amount Deposited:"
compoundInterest.Controls.Add(lblPrincipal)

// Text Box: Principal
let txtPrincipal = new TextBox()
txtPrincipal.Left <- 115
txtPrincipal.Top  <-  18
txtPrincipal.Width <- 64
txtPrincipal.Text <- "0.00"       
compoundInterest.Controls.Add(txtPrincipal)

// Label: Periods
let lblPeriods = new Label()
lblPeriods.Left <- 12
lblPeriods.Top <- 50
lblPeriods.Text <- "Periods:"
compoundInterest.Controls.Add(lblPeriods)

// Text Box: Periods
let txtPeriods = new TextBox()
txtPeriods.Left <- 115
txtPeriods.Top <-  47
txtPeriods.Width <- 45
txtPeriods.Text <- "0"
compoundInterest.Controls.Add(txtPeriods)

// Combo Box: Periods
let cbxPeriods = new ComboBox()
cbxPeriods.Left <- 166
cbxPeriods.Top  <-  47
cbxPeriods.Width <- 96
cbxPeriods.Text <- "Years" 
cbxPeriods.Items.AddRange([| "Days"; "Months"; "Years" |])
compoundInterest.Controls.Add(cbxPeriods)

// Label: Compounded
let lblCompounded = new Label()
lblCompounded.Left <- 12
lblCompounded.Top  <- 79
lblCompounded.Text <- "Compounded:"
compoundInterest.Controls.Add(lblCompounded)

// Combo Box: Compounded
let cbxCompounded = new ComboBox()
cbxCompounded.Left <- 115
cbxCompounded.Top  <-  76
cbxCompounded.Width <- 146
cbxCompounded.Items.AddRange([| "Daily"; "Monthly"; "Quarterly"; "Yearly" |])
compoundInterest.Controls.Add(cbxCompounded)

// Label: Interest Rate
let lblInterestRate = new Label()
lblInterestRate.Left <- 14
lblInterestRate.Top <- 109
lblInterestRate.Text <- "Interest Rate:"
compoundInterest.Controls.Add(lblInterestRate)

// Text Box: Interest Rate
let txtInterestRate = new TextBox()
txtInterestRate.Left  <- 115
txtInterestRate.Top   <- 106
txtInterestRate.Width <- 45
txtInterestRate.Text  <- "0.00" 
compoundInterest.Controls.Add(txtInterestRate)

let cbxCompoundedSelectedIndexChanged(e) =
    match cbxCompounded.SelectedIndex with
    | 0 -> // Daily
        match cbxPeriods.Text with
        | "Years" ->
            numberOfPeriods <- 1.00
            interestRate <- 12.05
        | "Months" ->
            numberOfPeriods <- 12.00
            interestRate <- 10.15
        | "Days" ->
            numberOfPeriods <- 360.00
            interestRate <- 9.95
        | _ ->
            numberOfPeriods <- 365.00
            interestRate <- 20.00

    | 1 -> // Monthly
        match cbxPeriods.Text with
        | "Years" ->
            numberOfPeriods <- 1.00
            interestRate <- 10.45
        | "Months" ->
            numberOfPeriods <- 12.00
            interestRate <- 9.65
        | "Days" ->
            numberOfPeriods <- 360.00
            interestRate <- 8.75
        | _ ->
            numberOfPeriods <- 365.00
            interestRate <- 20.00
                
    | 2 -> // Quarterly
        match cbxPeriods.Text with
        | "Years" ->
            numberOfPeriods <- 1.00
            interestRate <- 10.20
        | "Months" ->
            numberOfPeriods <- 12.00
            interestRate <- 8.60
        | "Days" ->
            numberOfPeriods <- 360.00
            interestRate <- 8.20
        | _ ->
            numberOfPeriods <- 365.00
            interestRate <- 20.00
              
    | 3 -> // Yearly
        match cbxPeriods.Text with
        | "Years" ->
            numberOfPeriods <- 1.00
            interestRate <- 9.15
        | "Months" ->
            numberOfPeriods <- 12.00
            interestRate <- 7.75
        | "Days" ->
            numberOfPeriods <- 360.00
            interestRate <- 6.35
        | _ ->
            numberOfPeriods <- 365.00
            interestRate <- 20.00
                
    | _ -> interestRate <- 20.00

    let strInterestRate = sprintf "%0.02f" interestRate
    txtInterestRate.Text <- strInterestRate

cbxCompounded.SelectedIndexChanged.Add cbxCompoundedSelectedIndexChanged

// Label: Percent
let lblPercent = new Label()
lblPercent.Left  <- 166
lblPercent.Top   <- 109
lblPercent.Width <- 20
lblPercent.Text  <- "%"
compoundInterest.Controls.Add(lblPercent)

// Button: Calculate
let btnCalculate = new Button()
btnCalculate.Left <- 186
btnCalculate.Top  <- 104
btnCalculate.Text <- "Calculate"
compoundInterest.Controls.Add(btnCalculate)

// Label: Future Value
let lblFutureValue = new Label()
lblFutureValue.Left <- 12
lblFutureValue.Top  <- 145
lblFutureValue.Text <- "Future Value:"
compoundInterest.Controls.Add(lblFutureValue)

// Text Box: Future Value
let txtFutureValue = new TextBox()
txtFutureValue.Left  <- 115
txtFutureValue.Top   <- 142
txtFutureValue.Width <-  64
txtFutureValue.Text  <- "0.00" 
compoundInterest.Controls.Add(txtFutureValue)

let btnCalculateClick(e) =
    let mutable periods   = 0.00
    let mutable principal = 0.00

    principal <- float txtPrincipal.Text
    interestRate <- (float txtInterestRate.Text) / 100.00
    periods <- float txtPeriods.Text

    let futureValue = principal * ((1.00 + (interestRate / numberOfPeriods)) ** (numberOfPeriods * periods))
    let strFutureValue = sprintf "%0.02f" futureValue
    txtFutureValue.Text <- strFutureValue
btnCalculate.Click.Add btnCalculateClick

// Button: Close
let btnClose = new Button()
btnClose.Left <- 186
btnClose.Top  <- 141
btnClose.Text <- "Close" 
let btnCloseClick(e) =
    compoundInterest. Close()
btnClose.Click.Add btnCloseClick
compoundInterest.Controls.Add btnClose   

Application.Run(compoundInterest)

Here are examples of running the program:

Compound Interest

Compound Interest

Pattern Matching and Conditional Statements

Conditional statements can be used in pattern matching. For example, an if statement can be used (nested) in a pattern (in an option clause of pattern matching). Here are examples:

open System
open System.Windows.Forms

// Federal Withholding Tax
let withholdingTaxes = new Form()
withholdingTaxes.Width <- 228
withholdingTaxes.Height <- 300
withholdingTaxes.Text <- "Federal Withholding Tax"

// Label: Marital Status
let lblMaritalStatus = new Label()
lblMaritalStatus.Left <- 12
lblMaritalStatus.Top  <- 18
lblMaritalStatus.Width <- 115
lblMaritalStatus.Text <- "Marital Status:"
withholdingTaxes.Controls.Add(lblMaritalStatus)

// Text Box: Marital Status
let cbxMaritalsStatus = new ComboBox()
cbxMaritalsStatus.Left  <- 132
cbxMaritalsStatus.Top   <- 15
cbxMaritalsStatus.Width <- 75
cbxMaritalsStatus.Items.AddRange([| "Single"; "Married" |])      
withholdingTaxes.Controls.Add(cbxMaritalsStatus)

// Label: Salary
let lblSalary = new Label()
lblSalary.Left <- 12
lblSalary.Top <-  48
lblSalary.Width <- 115
lblSalary.Text <- "Salary:"
withholdingTaxes.Controls.Add(lblSalary)

// Text Box: Salary
let txtSalary = new TextBox()
txtSalary.Left  <- 132
txtSalary.Top   <-  45
txtSalary.Width <-  75
txtSalary.Text  <- "0.00"
withholdingTaxes.Controls.Add(txtSalary)

// Label: Exemptions
let lblExemptions = new Label()
lblExemptions.Left  <- 12
lblExemptions.Top   <- 79
lblExemptions.Width <- 90
lblExemptions.Text  <- "Exemptions:"
withholdingTaxes.Controls.Add(lblExemptions)

// Text Box: Exemptions
let txtExemptions = new TextBox()
txtExemptions.Left  <- 132
txtExemptions.Top   <-  74
txtExemptions.Width <- 75
txtExemptions.Text  <- "0"
withholdingTaxes.Controls.Add(txtExemptions)

// Label: Allowances
let lblAllowances = new Label()
lblAllowances.Left  <-  12
lblAllowances.Top   <- 151
lblAllowances.Width <- 115
lblAllowances.Text  <- "Allowances:"
withholdingTaxes.Controls.Add(lblAllowances)

// Text Box: Allowances
let txtAllowances = new TextBox()
txtAllowances.Left  <- 132
txtAllowances.Top   <- 148
txtAllowances.Width <-  75
txtAllowances.Text  <- "0.00" 
withholdingTaxes.Controls.Add(txtAllowances)

// Label: Taxable Gross Wages
let lblTaxableGrossWages = new Label()
lblTaxableGrossWages.Left  <-  12
lblTaxableGrossWages.Top   <- 180
lblTaxableGrossWages.Width <- 120
lblTaxableGrossWages.Text  <- "Taxable Gross Wages:"
withholdingTaxes.Controls.Add(lblTaxableGrossWages)

// Text Box: Taxable Gross Wages
let txtTaxableGrossWages = new TextBox()
txtTaxableGrossWages.Left  <- 132
txtTaxableGrossWages.Top   <- 177
txtTaxableGrossWages.Width <-  75
txtTaxableGrossWages.Text  <- "0.00" 
withholdingTaxes.Controls.Add(txtTaxableGrossWages)

// Label: Federal Income Tax
let lblFederalIncomeTax = new Label()
lblFederalIncomeTax.Left  <-  12
lblFederalIncomeTax.Top   <- 209
lblFederalIncomeTax.Width <- 115
lblFederalIncomeTax.Text  <- "Federal Income Tax:"
withholdingTaxes.Controls.Add(lblFederalIncomeTax)

// Text Box: Federal Income Tax
let txtFederalIncomeTax = new TextBox()
txtFederalIncomeTax.Left  <- 132
txtFederalIncomeTax.Top   <- 208
txtFederalIncomeTax.Width <-  75
txtFederalIncomeTax.Text  <- "0.00" 
withholdingTaxes.Controls.Add(txtFederalIncomeTax)

let btnCalculateClick(e) =
    let mutable allowanceRate = 0.00
    let mutable withheldAmount = 0.00
    let salary = float txtSalary.Text
    let exemptions = float txtExemptions.Text
    let maritalStatus = cbxMaritalsStatus.Text

    allowanceRate <- 76.90
    let withheldingAllowances = allowanceRate * exemptions
    let taxableGrossWages = salary - withheldingAllowances

    match maritalStatus with
    | "Single" ->
        if    taxableGrossWages <=  44.00 then withheldAmount <- 0.00
        elif (taxableGrossWages >   44.00) && (taxableGrossWages <=  222.00) then withheldAmount <-            (taxableGrossWages -   44.00) * 10.00 / 100.00
        elif (taxableGrossWages >  222.00) && (taxableGrossWages <=  764.00) then withheldAmount <-   17.80 + ((taxableGrossWages -  222.00) * 15.00 / 100.00)
        elif (taxableGrossWages >  764.00) && (taxableGrossWages <= 1789.00) then withheldAmount <-   99.10 + ((taxableGrossWages -  764.00) * 25.00 / 100.00)
        elif (taxableGrossWages > 1789.00) && (taxableGrossWages <= 3685.00) then withheldAmount <-  355.05 + ((taxableGrossWages - 1789.00) * 28.00 / 100.00)
        elif (taxableGrossWages > 3685.00) && (taxableGrossWages <= 7958.00) then withheldAmount <-  886.23 + ((taxableGrossWages - 3685.00) * 33.00 / 100.00)
        elif (taxableGrossWages > 7958.00) && (taxableGrossWages <= 7990.00) then withheldAmount <- 2296.32 + ((taxableGrossWages - 7958.00) * 35.00 / 100.00)
        else                                                                      withheldAmount <- 2307.52 + ((taxableGrossWages - 7990.00) * 39.60 / 100.00)
    | "Married" ->
        if    taxableGrossWages <= 165.00 then withheldAmount <- 0.00
        elif (taxableGrossWages >  165.00) && (taxableGrossWages <=  520.00) then withheldAmount <-            (taxableGrossWages -  165.00) * 10.00 / 100.00
        elif (taxableGrossWages >  520.00) && (taxableGrossWages <= 1606.00) then withheldAmount <-   35.50 + ((taxableGrossWages -  520.00) * 15.00 / 100.00)
        elif (taxableGrossWages > 1606.00) && (taxableGrossWages <= 3073.00) then withheldAmount <-  198.40 + ((taxableGrossWages - 1606.00) * 25.00 / 100.00)
        elif (taxableGrossWages > 3073.00) && (taxableGrossWages <= 4597.00) then withheldAmount <-  565.15 + ((taxableGrossWages - 3073.00) * 28.00 / 100.00)
        elif (taxableGrossWages > 4597.00) && (taxableGrossWages <= 8079.00) then withheldAmount <-  991.87 + ((taxableGrossWages - 4597.00) * 33.00 / 100.00)
        elif (taxableGrossWages > 8079.00) && (taxableGrossWages <= 9105.00) then withheldAmount <- 2140.93 + ((taxableGrossWages - 8079.00) * 35.00 / 100.00)
        else                                                                      withheldAmount <- 2500.03 + ((taxableGrossWages - 9105.00) * 39.60 / 100.00)
    | _ -> ()

    txtAllowances.Text <- sprintf "%0.02f" withheldingAllowances
    txtTaxableGrossWages.Text  <- sprintf "%0.02f" taxableGrossWages
    txtFederalIncomeTax.Text  <- sprintf "%0.02f" withheldAmount

let btnCalculate = new Button()
btnCalculate.Left <- 132
btnCalculate.Top  <- 109
btnCalculate.Text <- "Calculate"
btnCalculate.Click.Add(btnCalculateClick)
withholdingTaxes.Controls.Add(btnCalculate)   

// Button: Close
let btnClose = new Button()
btnClose.Left <- 132
btnClose.Top  <- 238
btnClose.Text <- "Close" 
let btnCloseClick(e) =
    withholdingTaxes.Close()
btnClose.Click.Add(btnCloseClick)
withholdingTaxes.Controls.Add btnClose   

Application.Run(withholdingTaxes)

Here is an example of running the program:

Pattern Matching and Conditional Statements Pattern Matching and Conditional Statements

In the same way, you can nest a conditional statement that itself is nested in a matching pattern that itself is nested in another conditional statement or in another matching pattern, etc. Here is an example:

open System
open System.Windows.Forms

type MaritalStatus =
| Single
| Married

type PayrollFrequency =
| Weekly
| Biweekly
// | Semiweekly
// | Monthly
// | Quarterly
// | Semiannually
// | Annually

// Federal Withholding Tax
let withholdingTaxes = new Form()
withholdingTaxes.Width <- 240
withholdingTaxes.Height <- 325
withholdingTaxes.Text <- "Federal Withholding Tax"

let mutable maritalStatus : MaritalStatus = Single
let mutable frequency : PayrollFrequency = Weekly

// Label: Payroll Frequency
let lblPayrollFrequency = new Label()
lblPayrollFrequency.Left  <-  19
lblPayrollFrequency.Top   <-  23
lblPayrollFrequency.Width <- 115
lblPayrollFrequency.Text  <- "Payroll Frequency:"
withholdingTaxes.Controls.Add(lblPayrollFrequency)

// Text Box: Payroll Frequencies
let cbxPayrollFrequencies = new ComboBox()
cbxPayrollFrequencies.Left  <- 140
cbxPayrollFrequencies.Top   <-  20
cbxPayrollFrequencies.Width <-  75
cbxPayrollFrequencies.Items.AddRange([| "Weekly"; "Biweekly" |])

let cbxPayrollFrequenciesSelectedIndexChanged(e) =
    if cbxPayrollFrequencies.Text = "Biweekly" then
        frequency <- Biweekly
    else
        frequency <- Weekly

cbxPayrollFrequencies.Text <- "Weekly"
cbxPayrollFrequencies.SelectedIndexChanged.Add(cbxPayrollFrequenciesSelectedIndexChanged)
withholdingTaxes.Controls.Add(cbxPayrollFrequencies)

// Label: Marital Status
let lblMaritalStatus = new Label()
lblMaritalStatus.Left <- 19
lblMaritalStatus.Top  <- 52
lblMaritalStatus.Width <- 115
lblMaritalStatus.Text <- "Marital Status:"
withholdingTaxes.Controls.Add(lblMaritalStatus)

// Text Box: Marital Status
let cbxMaritalsStatus = new ComboBox()
cbxMaritalsStatus.Left  <- 140
cbxMaritalsStatus.Top   <- 49
cbxMaritalsStatus.Width <- 75
cbxMaritalsStatus.Items.AddRange([| "Single"; "Married" |])

let cbxMaritalsStatusSelectedIndexChanged(e) =
    if cbxMaritalsStatus.Text = "Married" then
        maritalStatus <- Married
    else
        maritalStatus <- Single

cbxMaritalsStatus.Text <- "Single"
cbxMaritalsStatus.SelectedIndexChanged.Add(cbxMaritalsStatusSelectedIndexChanged)
withholdingTaxes.Controls.Add(cbxMaritalsStatus)

// Label: Salary
let lblSalary = new Label()
lblSalary.Left <- 19
lblSalary.Top <-  81
lblSalary.Width <- 115
lblSalary.Text <- "Salary:"
withholdingTaxes.Controls.Add(lblSalary)

// Text Box: Salary
let txtSalary = new TextBox()
txtSalary.Left  <- 140
txtSalary.Top   <-  78
txtSalary.Width <-  75
txtSalary.Text  <- "0.00"
withholdingTaxes.Controls.Add(txtSalary)

// Label: Exemptions
let lblExemptions = new Label()
lblExemptions.Left  <- 19
lblExemptions.Top   <- 109
lblExemptions.Width <- 90
lblExemptions.Text  <- "Exemptions:"
withholdingTaxes.Controls.Add(lblExemptions)

// Text Box: Exemptions
let txtExemptions = new TextBox()
txtExemptions.Left  <- 140
txtExemptions.Top   <- 106
txtExemptions.Width <-  75
txtExemptions.Text  <- "0"
withholdingTaxes.Controls.Add(txtExemptions)

// Label: Allowances
let lblAllowances = new Label()
lblAllowances.Left  <-  19
lblAllowances.Top   <- 173
lblAllowances.Width <- 115
lblAllowances.Text  <- "Allowances:"
withholdingTaxes.Controls.Add(lblAllowances)

// Text Box: Allowances
let txtAllowances = new TextBox()
txtAllowances.Left  <- 140
txtAllowances.Top   <- 170
txtAllowances.Width <-  75
txtAllowances.Text  <- "0.00" 
withholdingTaxes.Controls.Add(txtAllowances)

// Label: Taxable Gross Wages
let lblTaxableGrossWages = new Label()
lblTaxableGrossWages.Left  <-  19
lblTaxableGrossWages.Top   <- 201
lblTaxableGrossWages.Width <- 120
lblTaxableGrossWages.Text  <- "Taxable Gross Wages:"
withholdingTaxes.Controls.Add(lblTaxableGrossWages)

// Text Box: Taxable Gross Wages
let txtTaxableGrossWages = new TextBox()
txtTaxableGrossWages.Left  <- 140
txtTaxableGrossWages.Top   <- 198
txtTaxableGrossWages.Width <-  75
txtTaxableGrossWages.Text  <- "0.00" 
withholdingTaxes.Controls.Add(txtTaxableGrossWages)

// Label: Federal Income Tax
let lblFederalIncomeTax = new Label()
lblFederalIncomeTax.Left  <-  19
lblFederalIncomeTax.Top   <- 229
lblFederalIncomeTax.Width <- 115
lblFederalIncomeTax.Text  <- "Federal Income Tax:"
withholdingTaxes.Controls.Add(lblFederalIncomeTax)

// Text Box: Federal Income Tax
let txtFederalIncomeTax = new TextBox()
txtFederalIncomeTax.Left  <- 140
txtFederalIncomeTax.Top   <- 226
txtFederalIncomeTax.Width <-  75
txtFederalIncomeTax.Text  <- "0.00" 
withholdingTaxes.Controls.Add(txtFederalIncomeTax)

// Button: Calculate
let btnCalculateClick(e) =
    let mutable allowanceRate = 0.00
    let mutable withheldAmount = 0.00
    let salary = float txtSalary.Text
    let exemptions = float txtExemptions.Text

    match frequency with
    | Weekly ->   allowanceRate <-  76.90
    | Biweekly -> allowanceRate <- 153.80

    let withheldingAllowances = allowanceRate * exemptions
    let taxableGrossWages     = salary - withheldingAllowances

    match frequency with
    | Weekly ->
        match maritalStatus with
        | Single ->
            if    taxableGrossWages <=  44.00                                    then withheldAmount <-    0.00
            elif (taxableGrossWages >   44.00) && (taxableGrossWages <=  222.00) then withheldAmount <-            (taxableGrossWages -   44.00) * 10.00 / 100.00
            elif (taxableGrossWages >  222.00) && (taxableGrossWages <=  764.00) then withheldAmount <-   17.80 + ((taxableGrossWages -  222.00) * 15.00 / 100.00)
            elif (taxableGrossWages >  764.00) && (taxableGrossWages <= 1789.00) then withheldAmount <-   99.10 + ((taxableGrossWages -  764.00) * 25.00 / 100.00)
            elif (taxableGrossWages > 1789.00) && (taxableGrossWages <= 3685.00) then withheldAmount <-  355.05 + ((taxableGrossWages - 1789.00) * 28.00 / 100.00)
            elif (taxableGrossWages > 3685.00) && (taxableGrossWages <= 7958.00) then withheldAmount <-  886.23 + ((taxableGrossWages - 3685.00) * 33.00 / 100.00)
            elif (taxableGrossWages > 7958.00) && (taxableGrossWages <= 7990.00) then withheldAmount <- 2296.32 + ((taxableGrossWages - 7958.00) * 35.00 / 100.00)
            else                                                                      withheldAmount <- 2307.52 + ((taxableGrossWages - 7990.00) * 39.60 / 100.00)
        | Married ->
            if    taxableGrossWages <= 165.00                                    then withheldAmount <-    0.00
            elif (taxableGrossWages >  165.00) && (taxableGrossWages <=  520.00) then withheldAmount <-            (taxableGrossWages -  165.00) * 10.00 / 100.00
            elif (taxableGrossWages >  520.00) && (taxableGrossWages <= 1606.00) then withheldAmount <-   35.50 + ((taxableGrossWages -  520.00) * 15.00 / 100.00)
            elif (taxableGrossWages > 1606.00) && (taxableGrossWages <= 3073.00) then withheldAmount <-  198.40 + ((taxableGrossWages - 1606.00) * 25.00 / 100.00)
            elif (taxableGrossWages > 3073.00) && (taxableGrossWages <= 4597.00) then withheldAmount <-  565.15 + ((taxableGrossWages - 3073.00) * 28.00 / 100.00)
            elif (taxableGrossWages > 4597.00) && (taxableGrossWages <= 8079.00) then withheldAmount <-  991.87 + ((taxableGrossWages - 4597.00) * 33.00 / 100.00)
            elif (taxableGrossWages > 8079.00) && (taxableGrossWages <= 9105.00) then withheldAmount <- 2140.93 + ((taxableGrossWages - 8079.00) * 35.00 / 100.00)
            else                                                                      withheldAmount <- 2500.03 + ((taxableGrossWages - 9105.00) * 39.60 / 100.00)
    | Biweekly ->
        match maritalStatus with
        | Single ->
            if    taxableGrossWages <=   88.00                                     then withheldAmount <-    0.00
            elif (taxableGrossWages >    88.00) && (taxableGrossWages <=   443.00) then withheldAmount <-            (taxableGrossWages -    88.00) * 10.00 / 100.00
            elif (taxableGrossWages >   443.00) && (taxableGrossWages <=  1529.00) then withheldAmount <-   35.50 + ((taxableGrossWages -   443.00) * 15.00 / 100.00)
            elif (taxableGrossWages >  1529.00) && (taxableGrossWages <=  3579.00) then withheldAmount <-  198.40 + ((taxableGrossWages -  1529.00) * 25.00 / 100.00)
            elif (taxableGrossWages >  3579.00) && (taxableGrossWages <=  7369.00) then withheldAmount <-  710.90 + ((taxableGrossWages -  3579.00) * 28.00 / 100.00)
            elif (taxableGrossWages >  7369.00) && (taxableGrossWages <= 15915.00) then withheldAmount <- 1772.10 + ((taxableGrossWages -  7369.00) * 33.00 / 100.00)
            elif (taxableGrossWages > 15915.00) && (taxableGrossWages <= 15981.00) then withheldAmount <- 4592.28 + ((taxableGrossWages - 15915.00) * 35.00 / 100.00)
            else                                                                        withheldAmount <- 4615.38 + ((taxableGrossWages - 15981.00) * 39.60 / 100.00)
        | Married ->
            if    taxableGrossWages <=  331.00                                     then withheldAmount <-    0.00
            elif (taxableGrossWages >   331.00) && (taxableGrossWages <=  1040.00) then withheldAmount <-            (taxableGrossWages -   331.00) * 10.00 / 100.00
            elif (taxableGrossWages >  1040.00) && (taxableGrossWages <=  3212.00) then withheldAmount <-   70.90 + ((taxableGrossWages -  1040.00) * 15.00 / 100.00)
            elif (taxableGrossWages >  3212.00) && (taxableGrossWages <=  6146.00) then withheldAmount <-  396.70 + ((taxableGrossWages -  3212.00) * 25.00 / 100.00)
            elif (taxableGrossWages >  6146.00) && (taxableGrossWages <=  9194.00) then withheldAmount <- 1130.20 + ((taxableGrossWages -  6146.00) * 28.00 / 100.00)
            elif (taxableGrossWages >  9194.00) && (taxableGrossWages <= 16158.00) then withheldAmount <- 1983.64 + ((taxableGrossWages -  9194.00) * 33.00 / 100.00)
            elif (taxableGrossWages > 16158.00) && (taxableGrossWages <= 18210.00) then withheldAmount <- 4281.76 + ((taxableGrossWages - 16158.00) * 35.00 / 100.00)
            else                                                                        withheldAmount <- 4999.96 + ((taxableGrossWages - 18210.00) * 39.60 / 100.00)

    txtAllowances.Text <- sprintf "%0.02f" withheldingAllowances
    txtTaxableGrossWages.Text  <- sprintf "%0.02f" taxableGrossWages
    txtFederalIncomeTax.Text  <- sprintf "%0.02f" withheldAmount

let btnCalculate = new Button()
btnCalculate.Left <- 140
btnCalculate.Top  <- 136
btnCalculate.Text <- "Calculate"
btnCalculate.Click.Add(btnCalculateClick)
withholdingTaxes.Controls.Add(btnCalculate)   

// Button: Close
let btnClose = new Button()
btnClose.Left <- 140
btnClose.Top  <- 261
btnClose.Text <- "Close" 
let btnCloseClick(e) =
    withholdingTaxes.Close()
btnClose.Click.Add(btnCloseClick)
withholdingTaxes.Controls.Add btnClose   

Application.Run(withholdingTaxes)

Here is an example of running the program:

Pattern Matching and Conditional Statements Pattern Matching and Conditional Statements

Home Copyright © 2015, FunctionX Home