To assist you with various types of operations on tuples and their items, the F# language provides a series of operators and built-in functions that can be applied directly to the members of a tuple. A tuple has built-in functionality to perform all operations using regular algebraic operators:
In the same way, you can perform all types of operations on the members of . Here is an example: open System
open System.Drawing
open System.Windows.Forms
let financialDecisionMaking = new System.Windows.Forms.Form(Text = "Business",
MaximizeBox = false,
ClientSize = new System.Drawing.Size(218, 150),
StartPosition = FormStartPosition.CenterScreen)
let (currentAssets, inventory, currentLiatilities) = (4841586.00, 682400.00, 2115351.00)
let lblCurrentAssets = new System.Windows.Forms.Label(AutoSize = true,
Text = "Current Assets:",
Location = new Point(23, 20))
financialDecisionMaking.Controls.Add lblCurrentAssets
let txtCurrentAssets = new System.Windows.Forms.TextBox(Text = string currentAssets,
Location = new Point(118, 17),
TextAlign = HorizontalAlignment.Right,
Size = new System.Drawing.Size(83, 20))
financialDecisionMaking.Controls.Add txtCurrentAssets
let lblInventory = new System.Windows.Forms.Label(AutoSize = true,
Text = "Inventory:",
Location = new System.Drawing.Point(23, 46))
financialDecisionMaking.Controls.Add(lblInventory)
let txtInventory = new System.Windows.Forms.TextBox(Text = string inventory,
Location = new Point(118, 44),
TextAlign = HorizontalAlignment.Right,
Size = new System.Drawing.Size(83, 20))
financialDecisionMaking.Controls.Add txtInventory
let lblCurrentLiabilities = new System.Windows.Forms.Label(AutoSize = true,
Text = "Current Liabilities:",
Location = new Point(23, 74))
financialDecisionMaking.Controls.Add lblCurrentLiabilities
let txtCurrentLiabilities = new System.Windows.Forms.TextBox(Text = string currentAssets,
Location = new Point(118, 71),
TextAlign = HorizontalAlignment.Right,
Size = new System.Drawing.Size(83, 20))
financialDecisionMaking.Controls.Add txtCurrentLiabilities
let lblLine = new System.Windows.Forms.Label(BackColor = System.Drawing.Color.Black,
Size = new System.Drawing.Size(176, 1),
Location = new System.Drawing.Point(25, 99))
financialDecisionMaking.Controls.Add lblLine
let lblQuickRatio = new System.Windows.Forms.Label(AutoSize = true,
Text = "Quick Ratio:",
Location = new System.Drawing.Point(23, 111))
financialDecisionMaking.Controls.Add lblQuickRatio
let txtQuickRatio = new System.Windows.Forms.TextBox(Location = new Point(118, 109),
TextAlign = HorizontalAlignment.Right,
Size = new System.Drawing.Size(83, 20))
txtQuickRatio.Text <- string (sprintf "%0.03f" ((currentAssets - inventory) / currentLiatilities))
financialDecisionMaking.Controls.Add txtQuickRatio
do System.Windows.Forms.Application.Run financialDecisionMaking
This would produce:
If you create a function in curried form that takes two parameters, when calling the function, you can pass its arguments as a tuple. This is referred to as applying a tuple to a function. To apply two values to a function, applying the values as a pair, use the <|| operator. The formula to follow is: Function <|| (Value1, Value2) The values are included in parentheses on the right side of the operator. Here is an example:
open System open System.Drawing open System.Windows.Forms let debtRatio = new Form(Text = "Dept Ratio", MaximizeBox = false, ClientSize = new System.Drawing.Size(222, 156), StartPosition = FormStartPosition.CenterScreen) let calculate debt assets = debt / assets let lblTotalDebt = new Label(AutoSize = true, Text = "Total Debt:", Location = new Point(22, 24)) debtRatio.Controls.Add lblTotalDebt let txtTotalDebt = new TextBox(Location = new Point(123, 21), Size = new System.Drawing.Size(75, 20)) debtRatio.Controls.Add txtTotalDebt let lblTotalAssets = new Label(AutoSize = true, Text = "Total Assets:", Location = new Point(22, 54)) debtRatio.Controls.Add lblTotalAssets let txtTotalAssets = new TextBox(Location = new Point(123, 51), Size = new System.Drawing.Size(75, 20)) debtRatio.Controls.Add txtTotalAssets let btnCalculate = new Button(Text = "Calculate", Location = new Point(123, 82), Size = new System.Drawing.Size(75, 23)) let lblDebtRatio = new Label(AutoSize = true, Text = "Debt Ratio:", Location = new System.Drawing.Point(23, 118)) debtRatio.Controls.Add lblDebtRatio let txtDebtRatio = new TextBox(Location = new Point(123, 115), Size = new System.Drawing.Size(75, 20)) debtRatio.Controls.Add txtDebtRatio let btnCalculateClick (e : EventArgs) = let mutable totalDebt = 0.00 let mutable totalAssets = 0.00 try totalDebt <- float txtTotalDebt.Text with | :? FormatException as exc -> MessageBox.Show("The value you provided for the total debt is not valid", "Debt Ratio", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore; try totalAssets <- float txtTotalAssets.Text with | :? FormatException as exc -> MessageBox.Show("The value you provided for the total assets is not valid", "Debt Ratio", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore; let result = calculate <|| (totalDebt, totalAssets) txtDebtRatio.Text <- sprintf "%0.02f%s" (result * 100.00) "%" btnCalculate.Click.Add btnCalculateClick debtRatio.Controls.Add btnCalculate do System.Windows.Forms.Application.Run debtRatio This would produce:
You can also apply one value to the left of the function and a pair to the right of the function. The alternative is to use the ||> in which case the positions of the function and the values in parentheses are inversed. Here is an example: let btnCalculateClick (e : EventArgs) =
let mutable totalDebt = 0.00
let mutable totalAssets = 0.00
try
totalDebt <- float txtTotalDebt.Text
with
| :? FormatException as exc -> MessageBox.Show("The value you provided for the total debt is not valid", "Debt Ratio",
MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore;
try
totalAssets <- float txtTotalAssets.Text
with
| :? FormatException as exc -> MessageBox.Show("The value you provided for the total assets is not valid", "Debt Ratio",
MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore;
let result = (totalDebt, totalAssets) ||> calculate
txtDebtRatio.Text <- sprintf "%0.02f%s" (result * 100.00) "%"
To apply three values to a function, use the <||| operator. The formula to use is: Function <||| (Value1, Value2, Value3) The function is in curried form and takes three parameters. When calling the function, use the <||| operator but pass the arguments as a triple. Here is an example: let getFullName a b c = a + " " + b + " " + c let fullName = getFullName <||| ("Jean", "Philippe", "Marthely") An alternative is to use the |||> operator. In this case, the values and their parentheses must appear first (to the left of the operator) while the function must appear to the right.
When studying functions, we saw how you can apply a value to a function. In reality, such a a value can be a tuple. This allows you to apply a single value that happens to hold many sub-values.
Consider the following tuple: let numbers = (1, 4, 6, 12, 36)
If you create such a tuple where you don't name the members and simply assign that tuple to a variable, there is no tuple built-in operator to access each member. A solution is to use pattern matching. To use it, create a matching pattern with one case. The case must have the same number of elements as the tuple. In the tuple, create a name for each element. The name can be a letter or any word that follows the rules for names in F#. The case is followed by -> and what you want to do. From there, you can access each value of the tuple using its corresponding name in the matching case. Here is an example: let numbers = (1, 4, 6, 12, 36)
match numbers with
| (one, four, six, twelve, thirtySix) -> printfn "Numbers: %d, %d, %d, %d, %d" one four six twelve thirtySix
Of course, you can consider any of the names in the case as a value and use it any way you want. Here is an example: let numbers = (1, 4, 6, 12, 36)
match numbers with
| (one, four, six, twelve, thirtySix) ->
let number = twelve * 2
One of the striking features of tuples is that a parameter can be passed with a simple name to a function. That function can treat the parameter as a tuple. As a consequence, a single parameter can carry as many values as possible. In the body of the function, you retrieve values from the parameter. One way you can do this is with pattern matching. This can be done as follows: let calculate(schedule) = match schedule with | value1, value2, value3, value4 -> . . . In the same way, you pass as many parameters as possible and any of them can be treated as a tuple that carries many values. When calling the function, you must provide the appropriate number of values for each parameter. The values of a parameter used as tuple should be passed in their own paratheses. Here is an example:
open System open System.Drawing open System.Windows.Forms let stockTrading = new Form(Text = "Stock Trade", MaximizeBox = false, ClientSize = new System.Drawing.Size(222, 156), StartPosition = FormStartPosition.CenterScreen) let calculate(schedule1, schedule2, schedule3, schedule4, schedule5, schedule6, shares, price) = let principal = shares * price let mutable commission = 0.00 match schedule1 with | a1, a2, a3, a4 -> if (principal >= a1) && (principal <= a2) then commission <- a3 + (principal * a4 / 100.00) match schedule2 with | b1, b2, b3, b4 -> if (principal >= b1) && (principal <= b2) then commission <- b3 + (principal * b4 / 100.00) match schedule3 with | c1, c2, c3, c4 -> if (principal >= c1) && (principal <= c2) then commission <- c3 + (principal * c4 / 100.00) match schedule4 with | d1, d2, d3, d4 -> if (principal >= d1) && (principal <= d2) then commission <- d3 + (principal * d4 / 100.00) match schedule5 with | e1, e2, e3, e4 -> if (principal >= e1) && (principal <= e2) then commission <- e3 + (principal * e4 / 100.00) match schedule6 with | f1, f2, f3 -> if principal >= f1 then commission <- f2 + (principal * f3 / 100.00) principal + commission let lblNumberOfShares = new Label(AutoSize = true, Text = "Number of Shares:", Location = new Point(22, 24)) stockTrading.Controls.Add lblNumberOfShares let txtNumberOfShares = new TextBox(Location = new Point(123, 21), Size = new System.Drawing.Size(75, 20)) stockTrading.Controls.Add txtNumberOfShares let lblPricePerShare = new Label(AutoSize = true, Text = "Price Per Share:", Location = new Point(22, 54)) stockTrading.Controls.Add lblPricePerShare let txtPricePerShare = new TextBox(Location = new Point(123, 51), Size = new System.Drawing.Size(75, 20)) stockTrading.Controls.Add txtPricePerShare let btnCalculate = new Button(Text = "Calculate", Location = new Point(123, 82), Size = new System.Drawing.Size(75, 23)) let lbltotalInvestment = new Label(AutoSize = true, Text = "Total Investment:", Location = new System.Drawing.Point(23, 118)) stockTrading.Controls.Add lbltotalInvestment let txttotalInvestment = new TextBox(Location = new Point(123, 115), Size = new System.Drawing.Size(75, 20)) stockTrading.Controls.Add txttotalInvestment let btnCalculateClick (e : EventArgs) = let mutable numberofShares = 0.00 let mutable pricePerShare = 0.00 try numberofShares <- float txtNumberOfShares.Text with | :? FormatException as exc -> MessageBox.Show("The value you provided for the number of shares is not correct", "Stock Trade", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore; try pricePerShare <- float txtPricePerShare.Text with | :? FormatException as exc -> MessageBox.Show("The value you provided for the price per share is not correct", "Stock Trade", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore; let result = calculate(( 0.00, 2499.00, 28.50, 1.65), ( 2500.00, 5999.00, 55.75, 1.05), ( 6000.00, 19999.00, 65.85, 0.75), ( 20000.00, 49999.00, 80.00, 0.35), ( 50000.00, 499999.00, 145.50, 0.15), (500000.00, 225.00, 0.05), numberofShares, pricePerShare) txttotalInvestment.Text <- sprintf "%0.02f" result btnCalculate.Click.Add btnCalculateClick stockTrading.Controls.Add btnCalculate do System.Windows.Forms.Application.Run stockTrading If. Here is an example:
A member of a tuple can be of a record type. Before creating the tuple, you should (must) first create the record type and an object from it. When creating the tuple, add the record object in the placeholder in the parentheses. The combinations are up to you:
After creating the tuple, you can access it as one object. If you want to access the individual elements of the tuple, you can use a matching pattern whose case would provide a name in the placeholder of each element. Once you get to the record object, you can access its members and use them as you see fit. Here is an example: open System open System.Drawing open System.Windows.Forms type Customer = { AccountNumber : string CustomerName : string HomeAddress : string } let client = { AccountNumber = "2048-5094" CustomerName = "Victorine Barrett" HomeAddress = "14808 Executive Blvd, Rockville, MD 20853" } let prepareBill(first, second, third, consumption) = let (a, b) = first let (c, d) = second if consumption <= b then consumption * a elif consumption <= d then consumption * c else consumption * third // Dialog Box: Gas Utility Company - Customer Bill Summary let gasUtilityCompanyBillPreparation : Form = new Form(MaximizeBox = false, MinimizeBox = false, Text = "Gas Utility Company", FormBorderStyle = FormBorderStyle.FixedDialog, ClientSize = new System.Drawing.Size(214, 112), StartPosition = FormStartPosition.CenterScreen) // Label: Account Number let lblBillPreparationAccountNumber = new Label(AutoSize = true, Text = "Account #:", Location = new System.Drawing.Point(20, 16)) gasUtilityCompanyBillPreparation.Controls.Add lblBillPreparationAccountNumber // Text Box: Account Number let txtBillPreparationAccountNumber = new TextBox(Size = new System.Drawing.Size(75, 20), Location = new System.Drawing.Point(122, 13)) gasUtilityCompanyBillPreparation.Controls.Add txtBillPreparationAccountNumber // Label: CCF Consumption let lblBillPreparationCCFConsumption = new Label(AutoSize = true, Text = "CCF Consumption:", Location = new System.Drawing.Point(22, 45)) gasUtilityCompanyBillPreparation.Controls.Add lblBillPreparationCCFConsumption // Text Box: CCF Consumption let txtBillPreparationCCFConsumption = new TextBox(Size = new System.Drawing.Size(75, 20), Location = new System.Drawing.Point(122, 42)) gasUtilityCompanyBillPreparation.Controls.Add txtBillPreparationCCFConsumption // ---------------------------------------------------------------------------------------------- // Form: Gas Utility Company - Customer Bill Summary let gasUtilityCompany : Form = new Form(MaximizeBox = false, Text = "Gas Utility Company - Bill Summary", ClientSize = new System.Drawing.Size(362, 202), StartPosition = FormStartPosition.CenterScreen) // Label: Bill Number let lblBillNumber = new Label(Text = "Bill #:", AutoSize = true, Location = new Point(18, 18)) gasUtilityCompany.Controls.Add lblBillNumber // Text Box: Bill Number let txtBillNumber = new TextBox(Size = new System.Drawing.Size(75, 20), Location = new System.Drawing.Point(118, 15)) gasUtilityCompany.Controls.Add txtBillNumber // Label: Account Number let lblAccountNumber = new Label(AutoSize = true, Text = "Account #:", Location = new System.Drawing.Point(18, 44)) gasUtilityCompany.Controls.Add lblAccountNumber // Text Box: Account Number let txtAccountNumber = new TextBox(Size = new System.Drawing.Size(75, 20), Location = new System.Drawing.Point(118, 44)) gasUtilityCompany.Controls.Add txtAccountNumber // Label: Customer Name let lblCustomerName = new Label(AutoSize = true, Text = "Customer Name:", Location = new System.Drawing.Point(18, 70)) gasUtilityCompany.Controls.Add lblCustomerName // Text Box: Customer Name let txtCustomerName = new TextBox(Size = new System.Drawing.Size(160, 20), Location = new System.Drawing.Point(118, 67)) gasUtilityCompany.Controls.Add txtCustomerName // Label: Home Address let lblHomeAddress = new Label(AutoSize = true, Text = "Home Address:", Location = new System.Drawing.Point(18, 96)) gasUtilityCompany.Controls.Add lblHomeAddress // Text Box: Home Address let txtHomeAddress = new System.Windows.Forms.TextBox(Size = new System.Drawing.Size(224, 20), Location = new System.Drawing.Point(118, 96)) gasUtilityCompany.Controls.Add txtHomeAddress // Label: Line let lblLine = new Label(BackColor = Color.Black, Location = new System.Drawing.Point(20, 127), Size = new System.Drawing.Size(322, 1)) gasUtilityCompany.Controls.Add lblLine // Label: CCF Consumption let lblCCFConsumption = new Label(AutoSize = true, Text = "CCF Consumption:", Location = new System.Drawing.Point(18, 144)) gasUtilityCompany.Controls.Add lblCCFConsumption // Text Box: CCF Consumption let txtCCFConsumption = new TextBox(Size = new System.Drawing.Size(75, 20), Location = new System.Drawing.Point(118, 141)) gasUtilityCompany.Controls.Add txtCCFConsumption // Label: Amount Due let lblAmountDue = new Label(AutoSize = true, Text = "Amount Due:", Location = new System.Drawing.Point(201, 144)) gasUtilityCompany.Controls.Add lblAmountDue // Text Box: Amount Due let txtAmountDue = new TextBox(Location = new Point(277, 141), Size = new System.Drawing.Size(65, 20)) gasUtilityCompany.Controls.Add txtAmountDue // Button: Close let btnClose = new Button(Text = "Close", Location = new System.Drawing.Point(267, 172)) let btnCloseClick e = gasUtilityCompany.Close() btnClose.Click.Add btnCloseClick gasUtilityCompany.Controls.Add btnClose let gasUtilityCompanyLoad e = gasUtilityCompanyBillPreparation.ShowDialog() |> ignore // Button: Evaluate let btnEvaluate = new Button(Text = "Evaluate", Location = new System.Drawing.Point(122, 77)) let btnEvaluateClick e = let mutable consumption = 0.00 if String.IsNullOrEmpty txtBillPreparationAccountNumber.Text then MessageBox.Show("You must enter a customer account number", "Gas Utility Company", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore if String.IsNullOrEmpty txtBillPreparationCCFConsumption.Text then MessageBox.Show("You must enter the amount of gas the customer used", "Gas Utility Company", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore let acntNumber = txtBillPreparationAccountNumber.Text try consumption <- float txtBillPreparationCCFConsumption.Text with | :? FormatException as exc -> MessageBox.Show("The amount of gas consumption you provided is not a valid number", "Gas Utility Company", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore if acntNumber = client.AccountNumber then let bill = (100001, client, consumption) match bill with | (nbr, payer, cons) -> txtBillNumber.Text <- string nbr txtAccountNumber.Text <- payer.AccountNumber txtCustomerName.Text <- payer.CustomerName txtHomeAddress.Text <- payer.HomeAddress txtCCFConsumption.Text <- sprintf "%0.02f" cons let amtDue = prepareBill ((0.7458, 50.00), (0.5866, 150.00), 0.3582, consumption) txtAmountDue.Text <- sprintf "%0.02f" amtDue (* The following would work also let (a, b, c) = (100001, client, consumption) txtBillNumber.Text <- string a txtAccountNumber.Text <- b.AccountNumber txtCustomerName.Text <- b.CustomerName txtHomeAddress.Text <- b.HomeAddress txtCCFConsumption.Text <- sprintf "%0.02f" c let amtDue = prepareBill ((0.7458, 50.00), (0.6566, 150.00), 0.5824, consumption) txtAmountDue.Text <- sprintf "%0.02f" amtDue*) else MessageBox.Show("There is no customer with that account number", "Gas Utility Company", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore gasUtilityCompanyBillPreparation.Close() gasUtilityCompany.Load.Add gasUtilityCompanyLoad btnEvaluate.Click.Add btnEvaluateClick gasUtilityCompanyBillPreparation.Controls.Add btnEvaluate [<EntryPoint>] let main argv = Application.Run gasUtilityCompany 0 // return an integer exit code This would produce:
A member of a record can be a tuple. To create the member, provide its name and specify its data type as a combination of types that are separated by *. Here is an example: type RentalContract = {
ContractNumber : int
MusicalInstrument : int * string * float }
When creating the object for the record, assign the value of a tuple member as you would for a variable. Here are examples: type RentalContract = { ContractNumber : int ProcessedBy : string * string MusicalInstrument : int * string * float Customer : int * string * string * char RentStartDate : string } let contract = { ContractNumber = 100001 ProcessedBy = ("2036-4950", "Joshua Melmann") MusicalInstrument = (930485, "Roland JUNO-Gi Synthesizer", 1.25) Customer = (29374, "Rebecca", "Mewes", 'F') RentStartDate = "06/12/2015" } You can then access each member of the object. Remember that you can use a matching pattern to access each member of a tuple.
Each member of a tuple can be of any type, including a class or structure. When creating the tuple, you can first create each object. In the tuple, use the name of the object in the desired placeholder. Here is an example: type Employee(nbr, name) = let mutable n = nbr let mutable m = name member this.EmployeeNumber with get() = n and set(value) = n <- value member this.FullName with get() = m and set(value) = m <- value type FoodItem(code, name, price) = let mutable cd = code let mutable nm = name let mutable pr = price member this.ItemCode with get() = cd and set(value) = cd <- value member this.FoodName with get() = nm and set(value) = nm <- value member this.UnitPrice with get() = pr and set(value) = pr <- value let clerk = Employee(60284, "Frank Evers") let food = FoodItem("LS01", "Sweet and Sour Chicken", "5.95") let order = (clerk, food) You don't have to first create the objects outside the tuple. You can create the objects directly in the tuple. Here is an example: let order = (Employee(60284, "Frank Evers"), FoodItem("LS01", "Sweet and Sour Chicken", "5.95")) You can access the members of the tuple as we have done so far. If you want to access each member, you can create a matching pattern. From the option, the first member of the case represents the class of the first element of the tuple. This means that the first member of the case gives you access to the members of the class of the first element. The second element of the case gives you access to the members of the class of the second object, and so on. Here is an example: type Employee(nbr, name) = let mutable n = nbr let mutable m = name member this.EmployeeNumber with get() = n and set(value) = n <- value member this.FullName with get() = m and set(value) = m <- value type FoodItem(code, name, price) = let mutable cd = code let mutable nm = name let mutable pr = price member this.ItemCode with get() = cd and set(value) = cd <- value member this.FoodName with get() = nm and set(value) = nm <- value member this.UnitPrice with get() = pr and set(value) = pr <- value let order = (Employee(60284, "Frank Evers"), FoodItem("LS01", "Sweet and Sour Chicken", 5.95)) You can create groups for each class by including the appropriate members in individual tuples and access them like that. Because the class members are identifiable, you can access each by its name and use it as you see fit. In the same way, you can create a tuple that has as many objects as you want, and you can use a combination of objects and values of primitive types in a tuple. If you want to specify the type of each member of the tuple, after the name of the variable, type : followed by the types separated by *. Here is one example: type Employee(nbr, name) = let mutable n = nbr let mutable m = name member this.EmployeeNumber with get() = n and set(value) = n <- value member this.FullName with get() = m and set(value) = m <- value type FoodItem(code, name, price) = let mutable cd = code let mutable nm = name let mutable pr = price member this.ItemCode with get() = cd and set(value) = cd <- value member this.FoodName with get() = nm and set(value) = nm <- value member this.UnitPrice with get() = pr and set(value) = pr <- value let clerk = Employee(60284, "Frank Evers") let food = FoodItem("LS01", "Sweet and Sour Chicken", "5.95") let order : Employee * FoodItem = (clerk, food) Here is another example: type Employee(nbr, name) = let mutable n = nbr let mutable m = name member this.EmployeeNumber with get() = n and set(value) = n <- value member this.FullName with get() = m and set(value) = m <- value type FoodItem(code, name, price) = let mutable cd = code let mutable nm = name let mutable pr = price member this.ItemCode with get() = cd and set(value) = cd <- value member this.FoodName with get() = nm and set(value) = nm <- value member this.UnitPrice with get() = pr and set(value) = pr <- value let order : int * string * Employee * FoodItem * float = (1001, "06/18/2015", Employee(60284, "Frank Evers"), FoodItem("LS01", "Sweet and Sour Chicken", 5.95), 15.00)
A method of a class can return a method when it has performed its action. The method can be passed its own parameter(s) or it can use (a) parameter(s) from a constructor. Here are examples: open System open System.Drawing open System.Windows.Forms type TimeSheet(salary, mon, tue, wed, thu, fri, sat, sun) = let sal = ref salary let overtimeSalary = !sal * 1.50 member this.HourlySalary with get() = !sal and set(value) = sal := value // Returning a Tuple from a method member this.GetMondaySummary() = let regTime = if mon <= 8.00 then mon else 8.00 let overTime = if mon <= 8.00 then 0.00 else mon - 8.00 let regPay = regTime * !sal let overPay = overTime * overtimeSalary (regTime, overTime, regPay, overPay) member this.GetTuesdaySummary() = let regTime = if tue <= 8.00 then tue else 8.00 let overTime = if tue <= 8.00 then 0.00 else tue - 8.00 let regPay = (if tue <= 8.00 then tue else 8.00) * !sal let overPay = (if tue <= 8.00 then 0.00 else tue - 8.00) * overtimeSalary (regTime, overTime, regPay, overPay) member this.GetWednesdaySummary() = let regTime = if wed <= 8.00 then wed else 8.00 let overTime = if wed <= 8.00 then 0.00 else wed - 8.00 let regPay = (if wed <= 8.00 then wed else 8.00) * !sal let overPay = (if wed <= 8.00 then 0.00 else wed - 8.00) * overtimeSalary (regTime, overTime, regPay, overPay) member this.GetThursdaySummary() = ((if thu <= 8.00 then thu else 8.00), (if thu <= 8.00 then 0.00 else thu - 8.00), ((if thu <= 8.00 then thu else 8.00) * !sal), ((if thu <= 8.00 then 0.00 else thu - 8.00) * overtimeSalary)) member this.GetFridaySummary() = ((if fri <= 8.00 then fri else 8.00), (if fri <= 8.00 then 0.00 else fri - 8.00), ((if fri <= 8.00 then fri else 8.00) * !sal), ((if fri <= 8.00 then 0.00 else fri - 8.00) * overtimeSalary)) member this.GetSaturdaySummary() = ((if sat <= 8.00 then sat else 8.00), (if sat <= 8.00 then 0.00 else sat - 8.00), ((if sat <= 8.00 then sat else 8.00) * !sal), ((if sat <= 8.00 then 0.00 else sat - 8.00) * overtimeSalary)) member this.GetSundaySummary() = ((if sun <= 8.00 then sun else 8.00), (if sun <= 8.00 then 0.00 else sun - 8.00), ((if sun <= 8.00 then sun else 8.00) * !sal), ((if sun <= 8.00 then 0.00 else sun - 8.00) * overtimeSalary)) // Form: Time Sheet Pay Summary let timeSheetPaySummary : Form = new Form(ClientSize = new Size(524, 338), MaximizeBox = false, Text = "Time Sheet and Pay Summary", StartPosition = FormStartPosition.CenterScreen) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(22, 24), AutoSize = true, Text = "Hourly Salary:")) let txtHourlySalary : TextBox = new TextBox(Location = new Point(102, 21), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) timeSheetPaySummary.Controls.Add txtHourlySalary timeSheetPaySummary.Controls.Add(new Label(Location = new Point( 99, 57), AutoSize = true, Text = "Monday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(156, 57), AutoSize = true, Text = "Tuesday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(210, 57), AutoSize = true, Text = "Wednesday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(274, 57), AutoSize = true, Text = "Thursday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(329, 57), AutoSize = true, Text = "Friday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(386, 57), AutoSize = true, Text = "Saturday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(441, 57), AutoSize = true, Text = "Sunday")) let txtTimeSheetMonday : TextBox = new TextBox(Location = new Point(102, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtTimeSheetTuesday : TextBox = new TextBox(Location = new Point(159, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtTimeSheetWednesday : TextBox = new TextBox(Location = new Point(216, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtTimeSheetThursday : TextBox = new TextBox(Location = new Point(273, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtTimeSheetFriday : TextBox = new TextBox(Location = new Point(330, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtTimeSheetSaturday : TextBox = new TextBox(Location = new Point(387, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtTimeSheetSunday : TextBox = new TextBox(Location = new Point(444, 76), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) timeSheetPaySummary.Controls.AddRange([| txtTimeSheetMonday; txtTimeSheetTuesday; txtTimeSheetWednesday; txtTimeSheetThursday; txtTimeSheetFriday; txtTimeSheetSaturday; txtTimeSheetSunday |]) let btnSummarize : Button = new Button(Location = new Point(27, 111), Size = new Size(468, 35), Text = "Summarize") timeSheetPaySummary.Controls.Add btnSummarize timeSheetPaySummary.Controls.Add(new Label(Location = new Point( 99, 159), AutoSize = true, Text = "Monday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(156, 159), AutoSize = true, Text = "Tuesday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(210, 159), AutoSize = true, Text = "Wednesday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(274, 159), AutoSize = true, Text = "Thursday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(329, 159), AutoSize = true, Text = "Friday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(386, 159), AutoSize = true, Text = "Saturday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(441, 159), AutoSize = true, Text = "Sunday")) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(23, 185), AutoSize = true, Text = "Regular Time:")) let txtSummaryMonRegularTime : TextBox = new TextBox(Location = new Point(102, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryTueRegularTime : TextBox = new TextBox(Location = new Point(159, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryWedRegularTime : TextBox = new TextBox(Location = new Point(216, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryThuRegularTime : TextBox = new TextBox(Location = new Point(273, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryFriRegularTime : TextBox = new TextBox(Location = new Point(330, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySatRegularTime : TextBox = new TextBox(Location = new Point(387, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySunRegularTime : TextBox = new TextBox(Location = new Point(444, 182), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) timeSheetPaySummary.Controls.AddRange([| txtSummaryMonRegularTime; txtSummaryTueRegularTime; txtSummaryWedRegularTime; txtSummaryThuRegularTime; txtSummaryFriRegularTime; txtSummarySatRegularTime; txtSummarySunRegularTime |]) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(23, 211), AutoSize = true, Text = "Overtime:")) let txtSummaryMonOvertime : TextBox = new TextBox(Location = new Point(102, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryTueOvertime : TextBox = new TextBox(Location = new Point(159, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryWedOvertime : TextBox = new TextBox(Location = new Point(216, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryThuOvertime : TextBox = new TextBox(Location = new Point(273, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryFriOvertime : TextBox = new TextBox(Location = new Point(330, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySatOvertime : TextBox = new TextBox(Location = new Point(387, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySunOvertime : TextBox = new TextBox(Location = new Point(444, 208), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) timeSheetPaySummary.Controls.AddRange([| txtSummaryMonOvertime; txtSummaryTueOvertime; txtSummaryWedOvertime; txtSummaryThuOvertime; txtSummaryFriOvertime; txtSummarySatOvertime; txtSummarySunOvertime|]) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(23, 237), AutoSize = true, Text = "Regular Pay:")) let txtSummaryMonRegularPay : TextBox = new TextBox(Location = new Point(102, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryTueRegularPay : TextBox = new TextBox(Location = new Point(159, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryWedRegularPay : TextBox = new TextBox(Location = new Point(216, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryThuRegularPay : TextBox = new TextBox(Location = new Point(273, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryFriRegularPay : TextBox = new TextBox(Location = new Point(330, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySatRegularPay : TextBox = new TextBox(Location = new Point(387, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySunRegularPay : TextBox = new TextBox(Location = new Point(444, 234), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) timeSheetPaySummary.Controls.AddRange([| txtSummaryMonRegularPay; txtSummaryTueRegularPay; txtSummaryWedRegularPay; txtSummaryThuRegularPay; txtSummaryFriRegularPay; txtSummarySatRegularPay; txtSummarySunRegularPay |]) timeSheetPaySummary.Controls.Add(new Label(Location = new Point(23, 263), AutoSize = true, Text = "Overtime Pay:")) let txtSummaryMonOvertimePay : TextBox = new TextBox(Location = new Point(102, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryTueOvertimePay : TextBox = new TextBox(Location = new Point(159, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryWedOvertimePay : TextBox = new TextBox(Location = new Point(216, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryThuOvertimePay : TextBox = new TextBox(Location = new Point(273, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummaryFriOvertimePay : TextBox = new TextBox(Location = new Point(330, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySatOvertimePay : TextBox = new TextBox(Location = new Point(387, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) let txtSummarySunOvertimePay : TextBox = new TextBox(Location = new Point(444, 260), Width = 51, Text = "0.00", TextAlign = HorizontalAlignment.Right) timeSheetPaySummary.Controls.AddRange([| txtSummaryMonOvertimePay; txtSummaryTueOvertimePay; txtSummaryWedOvertimePay; txtSummaryThuOvertimePay; txtSummaryFriOvertimePay; txtSummarySatOvertimePay; txtSummarySunOvertimePay |]) let btnSummarizeClick e = let hourlySalary = float txtHourlySalary.Text let mon = float txtTimeSheetMonday.Text let tue = float txtTimeSheetTuesday.Text let wed = float txtTimeSheetWednesday.Text let thu = float txtTimeSheetThursday.Text let fri = float txtTimeSheetFriday.Text let sat = float txtTimeSheetSaturday.Text let sun = float txtTimeSheetSunday.Text let ts = new TimeSheet(hourlySalary, mon, tue, wed, thu, fri, sat, sun) let (monRegTime, monOvertime, monRegPay, monOvertiPay) = ts.GetMondaySummary() let (tueRegTime, tueOvertime, tueRegPay, tueOvertiPay) = ts.GetTuesdaySummary() let (wedRegTime, wedOvertime, wedRegPay, wedOvertiPay) = ts.GetWednesdaySummary() let (thuRegTime, thuOvertime, thuRegPay, thuOvertiPay) = ts.GetThursdaySummary() let (friRegTime, friOvertime, friRegPay, friOvertiPay) = ts.GetFridaySummary() let (satRegTime, satOvertime, satRegPay, satOvertiPay) = ts.GetSaturdaySummary() let (sunRegTime, sunOvertime, sunRegPay, sunOvertiPay) = ts.GetSundaySummary() txtSummaryMonRegularTime.Text <- sprintf "%0.02f" monRegTime txtSummaryMonOvertime.Text <- sprintf "%0.02f" monOvertime txtSummaryMonRegularPay.Text <- sprintf "%0.02f" monRegPay txtSummaryMonOvertimePay.Text <- sprintf "%0.02f" monOvertiPay txtSummaryTueRegularTime.Text <- sprintf "%0.02f" tueRegTime txtSummaryTueOvertime.Text <- sprintf "%0.02f" tueOvertime txtSummaryTueRegularPay.Text <- sprintf "%0.02f" tueRegPay txtSummaryTueOvertimePay.Text <- sprintf "%0.02f" tueOvertiPay txtSummaryWedRegularTime.Text <- sprintf "%0.02f" wedRegTime txtSummaryWedOvertime.Text <- sprintf "%0.02f" wedOvertime txtSummaryWedRegularPay.Text <- sprintf "%0.02f" wedRegPay txtSummaryWedOvertimePay.Text <- sprintf "%0.02f" wedOvertiPay txtSummaryThuRegularTime.Text <- sprintf "%0.02f" thuRegTime txtSummaryThuOvertime.Text <- sprintf "%0.02f" thuOvertime txtSummaryThuRegularPay.Text <- sprintf "%0.02f" thuRegPay txtSummaryThuOvertimePay.Text <- sprintf "%0.02f" thuOvertiPay txtSummaryFriRegularTime.Text <- sprintf "%0.02f" friRegTime txtSummaryFriOvertime.Text <- sprintf "%0.02f" friOvertime txtSummaryFriRegularPay.Text <- sprintf "%0.02f" friRegPay txtSummaryFriOvertimePay.Text <- sprintf "%0.02f" friOvertiPay txtSummarySatRegularTime.Text <- sprintf "%0.02f" satRegTime txtSummarySatOvertime.Text <- sprintf "%0.02f" satOvertime txtSummarySatRegularPay.Text <- sprintf "%0.02f" satRegPay txtSummarySatOvertimePay.Text <- sprintf "%0.02f" satOvertiPay txtSummarySunRegularTime.Text <- sprintf "%0.02f" sunRegTime txtSummarySunOvertime.Text <- sprintf "%0.02f" sunOvertime txtSummarySunRegularPay.Text <- sprintf "%0.02f" sunRegPay txtSummarySunOvertimePay.Text <- sprintf "%0.02f" sunOvertiPay btnSummarize.Click.Add btnSummarizeClick // Button: Close let btnClose = new Button(Location = new System.Drawing.Point(420, 296), Text = "Close") let btnCloseClick e = timeSheetPaySummary.Close() btnClose.Click.Add btnCloseClick timeSheetPaySummary.Controls.Add btnClose do Application.Run timeSheetPaySummary Here is an example of executing the program:
Just as seen with functions, an argument passed to a method can be treated as a tuple. When implementing the method, you can just pass a single value. In the body of the method, declare many variables and initialize them as one with the parameter. Then access the members of the tuple and use them any way you want. When calling the method, produce the appropriate number of members of the tuple. Here is an example: open System open System.Drawing open System.Windows.Forms type Employee(emplNbr, fName, lName, salary) = member this.EmployeeNumber = emplNbr member this.FirstName = fName member this.LastName = lName member this.YearlySalary = salary type Payroll(prNbr, emplNbr) = let mutable pn : int = prNbr let mutable en : string = emplNbr member this.PayrollNumber = prNbr member this.EmployeeNumber = emplNbr member this.CalculateTotalTime time = let mon, tue, wed, thu, fri, sat, sun = time mon + tue + wed + thu + fri + sat + sun let empl = new Employee("92-840", "Martin", "Perhaps", 26.85) let pay = new Payroll(10001, "92-840") let totalTime = pay.CalculateTotalTime (8.00, 8.50, 10.00, 8.50, 9.50, 0.00, 0.00) let payrollPreparation : Form = new Form() payrollPreparation.MaximizeBox <- false payrollPreparation.Text <- "Payroll Preparation" payrollPreparation.ClientSize <- new System.Drawing.Size(264, 86) payrollPreparation.StartPosition <- FormStartPosition.CenterScreen // Label: Employee Number let lblEmployeeNumber = new Label(AutoSize = true, Text = "Employee #:", Location = new Point(21, 18)) payrollPreparation.Controls.Add lblEmployeeNumber // Text Box: Employee Number let txtEmployeeNumber = new TextBox(Location = new Point(101, 15), Size = new System.Drawing.Size(62, 20)) payrollPreparation.Controls.Add txtEmployeeNumber // Button: Find let btnFind = new Button(Location = new Point(169, 13), Text = "Find Payroll", Width = 85) // Label: Total Time Worked let lblTotalTimeWorked = new Label(AutoSize = true, Text = "Time Worked:", Location = new Point(21, 53)) payrollPreparation.Controls.Add lblTotalTimeWorked // Text Box: Total Time Worked let txtTotalTimeWorked = new TextBox(Location = new Point(101, 50), Size = new System.Drawing.Size(62, 20)) payrollPreparation.Controls.Add txtTotalTimeWorked let btnFindClick e = if String.IsNullOrEmpty txtEmployeeNumber.Text <> true then let emplNbr = txtEmployeeNumber.Text if emplNbr = empl.EmployeeNumber then txtTotalTimeWorked.Text <- sprintf "%0.02f" totalTime btnFind.Click.Add btnFindClick payrollPreparation.Controls.Add btnFind [<EntryPoint>] let main argv = Application.Run payrollPreparation 0 Here is an example of running the program:
Remember that you can specify the number of members of the tuple parameter by specifying their types. Here is an example: type Payroll(prNbr, emplNbr) = let mutable pn : int = prNbr let mutable en : string = emplNbr member this.PayrollNumber = prNbr member this.EmployeeNumber = emplNbr member this.CalculateTotalTime (time : float * float * float * float * float * float * float) = let mon, tue, wed, thu, fri, sat, sun = time mon + tue + wed + thu + fri + sat + sun
A property of a class can be created as a property. Normally, you can just create a property as member variable without specifying its data type. In the body of the class, to use the member as a tuple, you can declare a combination variable and initialize it with the combination with the tuple. You can then use each variable to access the members of the tuple. When creating an object from the class, provide the appropriate tuple as its values in the placeholder of the member. Here is an example: open System open System.Drawing open System.Windows.Forms type Employee(emplNbr, fName, lName, salary) = member this.EmployeeNumber = emplNbr member this.FirstName = fName member this.LastName = lName member this.YearlySalary = salary type Payroll(prNbr, emplNbr, time) = let mutable pn = prNbr let mutable en = emplNbr let mutable tm = time member this.PayrollNumber = prNbr member this.EmployeeNumber = emplNbr member this.TimeWorked = time member this.CalculateTotalTime() = let mon, tue, wed, thu, fri, sat, sun = tm mon + tue + wed + thu + fri + sat + sun let empl = new Employee("92-840", "Martin", "Perhaps", 26.85) let pay = new Payroll(10001, "92-840", (8.00, 8.50, 10.00, 8.50, 9.50, 0.00, 0.00)) let payrollPreparation : Form = new Form() payrollPreparation.MaximizeBox <- false payrollPreparation.Text <- "Payroll Preparation" payrollPreparation.ClientSize <- new System.Drawing.Size(264, 86) payrollPreparation.StartPosition <- FormStartPosition.CenterScreen // Label: Employee Number let lblEmployeeNumber = new Label(AutoSize = true, Text = "Employee #:", Location = new Point(21, 18)) payrollPreparation.Controls.Add lblEmployeeNumber // Text Box: Employee Number let txtEmployeeNumber = new TextBox(Location = new Point(101, 15), Size = new System.Drawing.Size(62, 20)) payrollPreparation.Controls.Add txtEmployeeNumber // Button: Find let btnFind = new Button(Location = new Point(169, 13), Text = "Find Payroll", Width = 85) // Label: Total Time Worked let lblTotalTimeWorked = new Label(AutoSize = true, Text = "Time Worked:", Location = new Point(21, 53)) payrollPreparation.Controls.Add lblTotalTimeWorked // Text Box: Total Time Worked let txtTotalTimeWorked = new TextBox(Location = new Point(101, 50), Size = new System.Drawing.Size(62, 20)) payrollPreparation.Controls.Add txtTotalTimeWorked let btnFindClick e = if String.IsNullOrEmpty txtEmployeeNumber.Text <> true then let emplNbr = txtEmployeeNumber.Text if emplNbr = empl.EmployeeNumber then txtTotalTimeWorked.Text <- sprintf "%0.02f" (pay.CalculateTotalTime()) btnFind.Click.Add btnFindClick payrollPreparation.Controls.Add btnFind [<EntryPoint>] let main argv = Application.Run payrollPreparation 0 When creating a property that is a tuple, if you want to indicate that it is a tuple, you can specify the types of its members. To do this, after the name of the mutable member, type a colon and the data type. Separate them with * from each other. Here is an example type Payroll(prNbr, emplNbr, time) =
let mutable pn : int = prNbr
let mutable en : string = emplNbr
let mutable tm : float * float * float * float * float * float * float = time
member this.PayrollNumber = prNbr
member this.EmployeeNumber = emplNbr
member this.TimeWorked = time
member this.CalculateTotalTime() =
let mon, tue, wed, thu, fri, sat, sun = tm
mon + tue + wed + thu + fri + sat + sun
In the same way, you can specify the types of the members of the tuple wherever it is supposed to be used. Here are examples: type Payroll(prNbr, emplNbr, time : float * float * float * float * float * float * float) = let mutable pn : int = prNbr let mutable en : string = emplNbr let mutable tm : float * float * float * float * float * float * float = time member this.PayrollNumber = prNbr member this.EmployeeNumber = emplNbr member this.TimeWorked : float * float * float * float * float * float * float = time member this.CalculateTotalTime() = let mon, tue, wed, thu, fri, sat, sun = tm mon + tue + wed + thu + fri + sat + sun
At this time, you may have found that a constructor doesn't take parameters in a curried form like normal functions or methods do. The parameters passed to a constructor are provided as a tuple. Consider the following constructor: type Customer(actNbr, name, emrg) = let mutable nbr = actNbr let mutable name = name let mutable emergency = emrg member this.AccountNumber with get() = nbr and set(value) = nbr <- value member this.FullName with get() = name and set(value) = name <- value member this.EmergencyInformation with get() = emergency and set(value) = emergency <- value Because F# is an inferred language, if you don't specify the type of a parameter, the construtor (or method) may not know the type of value of the parameter until the constructor (oe the method) is called. You can use this feature to pass a tuple to a constructor when creating an object. Here is an example: let client = Customer("9614-9203", ("James", 'D', "Watts"), ("Frank Watts", "(301) 402-6084")) If you need to access each member of a tuple, remember that you can use a matching tuple.
When you call a method that takes a tuple, you must provide the values of the tuple in the appropriate order. F# allows you to provide the values in the order of your choice. To do this, when calling the method, in the parentheses, type each parameter name followed by = and its value. Here is an example: type HotelRoom(number, roomType, rate) =
member this.RoomNumber = number
member this.RoomType = roomType
member this.DailyRate = rate
member this.CalculateInvoice(days, phoneCharge, discount) =
(float days * rate) + phoneCharge - (float days * rate * discount / 100.00)
let room = HotelRoom(104, "Conference Room", 450.00)
let days = 3
let phoneUse = 12.48
let total = room.CalculateInvoice(phoneCharge = 12.48, days = 3, discount = 20.00)
By default, you should use unique names for methods in a class. If you try creating two methods with the same name and the exact same signature (in the same class), you would receive an error. Fortunately, there is an alternative. You can provide different versions of the same method in a class. This is referred to as method overloading. Method overloading consists of having various signatures for the same method. This means that different methods can have the same name but different formats of parameters. One of the methods can be in curreid form and the other(s) take (a) tuple(s). This means that one version can be created like a function that takes parameters separated by spaces. The other versions can each take one or more tuples. Here are examples: type HotelRoom(number, roomType, rate) = member this.RoomNumber = number member this.RoomType = roomType member this.DailyRate = rate member this.CalculateInvoice days = float days * rate // Curried Form member this.CalculateInvoice (days, phoneCharge) = // Tuple Form: A pair (float days * rate) + phoneCharge member this.CalculateInvoice (days, phoneCharge, discountRate) = // Tuple Form (float days * rate) + phoneCharge - (float days * rate * discountRate / 100.00) let room110 = HotelRoom(roomType = "Conference Room", rate = 450.00, number = 110) let mutable days, phoneUse = 1, 0.00 // Calling the version with curried form let mutable total = room110.CalculateInvoice days let room102 = HotelRoom(roomType = "Bedroom", rate = 95.50, number = 102) days <- 5 phoneUse <- 7.46 // Calling the version with a paired tuple form total <- room102.CalculateInvoice(days, phoneUse) let room212 = HotelRoom(rate = 95.50, number = 212, roomType = "Bedroom") days <- 3 phoneUse <- 15.68 // Calling the version with tuple form total <- room212.CalculateInvoice(days, phoneUse, 20.00)
Each member of a tuple is a placeholder for any type. This means that each element (or the placeholder of an element) can be its own tuple. This allows you to create a tuple in another tuple or to create tuples in a tuple. When doing this, remember that each tuple must use its own parentheses. Here an example of a tuple that contains other tuples: ("529-385", ("Peter", "James", "Watson"), ("Julie watson", "240-144-0285")) Remember that you can write tuple members on separate lines to make the code easy to read. Here is an example: (529385, ("Peter", "Josh", "Watson"), ("Julie watson", "240-144-0285") ); As defined in the variable, the primary tuple contains three members. For our example, the first member is an account number and we used one value for it. The second member represents a name; we defined it as a tuple with three members. Our last member represents emergency contact information. We represent it as a tuple with two members (an emergency name and an emergency phone number). Of course, each tuple can use different types of values. |