Lists
Lists
Fundamentals of Lists
Overview of Lists
A list is a group of constant values of the same type. The list if immutable, meaning that once the list is created, it cannot change. Although this is the standard definition, we will still all types of operations you can perform on a list.
Introduction to Creating a List
To create a list, start with an opening square bracket "[" and end with a closing square bracket "]". Inside the brackets, create the members of the list. Each member ends with a semicolon. Here are examples:
// A list of numbers [ 12; 22; 48; 115; 306; ] // A list of characters [ 'c'; 'd'; 'g'; 'j'; 'm'; ] // A list of strings, names [ "Frank"; "James"; "Joshua"; "Mary"; ]
The semicolon on the last member is optional. On the other hand, you don't have to create all members on the same line. In fact, you can write the square brackets on their own lines and the members on a separate line after the opening square bracket. Here is an example:
[ "Frank"; "James"; "Joshua"; "Mary"; ]
Although you don't have to indent, indentation makes the list easier to read:
[ "Frank"; "James"; "Joshua"; "Mary"; ]
Another alternative is to have each member of the list on its own line. Here is an example:
[ "Frank"; "James"; "Joshua"; "Mary"; ];
If you decide to create each member on its own line, you can omit the semicolons. Here are examples:
[ "Frank" "James" "Joshua" "Mary" ];
An Empty List
A list is referred to as empty if it doesn't contain any item, but it is still considered a list. To create an empty list, type the square brackets but leave them empty. Here is an example:
[]
A list is a kind of variable. Although you can use it without naming it, if you plan to refer to it in different parts of your code, you should give it a name. To do this, declare a variable using the let keyword, followed by a name for the variable, and assign the list to it. Here is an example:
let numbers = [ 12; 22; 48; 115; 306 ]
Remember that the items can be separated from the square brackets by different lines:
let characters = [ 'c'; 'd'; 'g'; 'j'; 'm' ];
To store an empty list in a variable, assign empty square brackets to it. Here is an example:
let numbers = []
A list is a series of arranged items. If you want some items that are known in advance and they are consecutive, you can specify only the beginning and end of the series. When creating the list, in the square brackets, type the starting item, followed by .., and followed by the ending item. It is a good idea to put a space before and after .. to make it easier to read. Here are examples:
// A range of numbers [ 2 .. 8 ]; // A range of letters [ 'h' .. 'q' ];
Instead of creating a range from known constant values, the F# language proposes a keyword named for. It allows you to indicate only the begining and ending values. The basic formula is:
[ for variable-name in range -> body ]
The variable-name can be any lowercase letter or any name. The range is usually specified as start-value .. end-value. The body of the loop is created after the -> sign. It can simply consist of the variable-name . Here is an example:
[ for variable in 1 .. 8 -> variable ]
This is equivalent to numbers from 1 to 8:
[1; 2; 3; 4; 5; 6; 7; 8]
An alternative to use the -> operator is to use the do yield expression. Here is an example:
[ for variable in 1 .. 8 do yield variable ]
When you create a range, you specify the starting and the ending values. When the range is processed, the compiler will add 1 to the first value to get the second value. Then it would add 1 to each subsequent value to get the next value, until that next value is immediately less than or equal to the ending value. Instead of adding 1 to each value to get the next, you may want to use another incrementing scheme. That type of range is created using the skip range operator representd by .. ..
The formula to create a skip range is:
Start .. Step .. End
The algorithm works as follows:
Here is an example:
[ 3 .. 2 .. 20 ]
In this case, the range would start at 3. The value 2 would be added to the first, 3, to get the next. Then 2 would be added to the new value, and so on, until the new number is immediately lower than the last number specified in the range:
Numbers: [ 3; 5; 7; 9; 11; 13; 15; 17; 20 ]
As a consequence, the End value is included in the result if it gets out of range when the step is added to the previous value.
Looping a List
Looping consists of going through a series of values from a starting point to an ending point. The formula to follow is:
for identifier = start [ to | downto ] end do body
The for, the to, and the do keywords are required. The downto keyword can be used in place of the do keyword in some cases as we will see. The identifier is a name used to specify a local variable that will hold the current value as the series is being scanned. start represents the value by which to start counting and end is the value by which to stop. The body of the looping operation starts with the do keyword but is written on the next line. That body can contain any code you see fit. Here is an example that displays some numbers being counted:
for i = 1 to 5 do printfn "Number: %d" i
This would produce:
Number: 1 Number: 2 Number: 3 Number: 4 Number: 5 Press any key to close this window . . .
The start and end values can also come from previously declared variables.
It is possible to loop in a range of values. The formula to follow is:
for identifier in range do body
In this case, the range can consist of a starting and an ending values separated by two periods. Here is an example:
for i in 1 .. 5 do printfn "Number: %d" i;
This would produce the same result as above.
Instead of counting from a starting value to a known end, you may want to execute a statement from a begining value but continue as long as a certain condition exists. This is done using the while keyword. The formula to follow is:
while Condition do body
The while and the do keywords are required. The Condition is something that needs to be checked. It could be a conditional operation or anything that can produce a true or false result. After the do keyword, create a body for the loop. Here is an example:
let mutable a = 1; while a < 6 do printfn "Number: %d" a; a <- a + 1;
Creating Items From an Expression
Most of the time, you will create a looping range because you want the numbers to follow a certain pattern instead of simply incrementing. Here is an example:
[ for variable in 0 .. 15 -> variable * 5 ]
Although each member of a list must be a constant value, each value can be created from an expression. Here is an example:
[ for variable in 0 .. 15 do yield variable * 5 ]
Using a List
Introduction
To present a list of items, you can call the printf() or the printfn() function and use %A as the placeholder. If you had previously declared a variable for a list and had initialized it, you can specify its name as the placeholder of the printf() or the printfn() function. Here is an example:
let names = [ "Frank"; "James"; "Joshua"; "Mary" ]; printfn "%A" names;
This would produce:
["Frank"; "James"; "Joshua"; "Mary"] Press any key to close this window . . .
Instead for first declaring the variable, we saw that you can create a name-less list. In this case, you can provide that list directly in the placeholder. Here is an example:
printfn "%A" [ "Frank"; "James"; "Joshua"; "Mary" ];
You can also write the items on different lines. Here is an example:
printfn "%A" [ "Frank" "James" "Joshua" "Mary" ];
This would produce:
["Frank"; "James"; "Joshua"; "Mary"] Press any key to close this window . . .
Either way, this means that you don't have to first declare a variable for a list. You can just create the list directly where it is needed.
In the same way, you can use %A to show the values created from a range. Here is an example:
let range = [3 .. 12 ] printfn "Numbers: %A" range;
This would produce:
Numbers: [3; 4; 5; 6; 7; 8; 9; 10; 11; 12] Press any key to close this window . . .
You use the same technique for a skip-range. Here is an example:
let skipRange = [3 .. 2 .. 20 ] printfn "Numbers: %A" skipRange;
This would produce:
Numbers: [3; 5; 7; 9; 11; 13; 15; 17; 19] Press any key to close this window . . .
For Each Item in a List
To help you visit each member of a list, the F# language provides looping operation that uses the for keyword. The formula to follow is:
for identifier / pattern in list do body
The for, the in, and the do keywords are required. The identifier could be a variable name that will hold the value to be retrieved from the list. Here is an example:
for i in [ "Frank"; "James"; "Joshua"; "Mary" ] do printfn "Name: %s" i;
This would produce:
Name: Frank Name: James Name: Joshua Name: Mary Press any key to close this window . . .
As Long As (while) it is not the End of the List
Besides (or instead of) a for loop, you can use the while operator to visit each member of the list. As done for the for operator, if you decide (or want, or have) to use while, make sure you specify where and how to start the visit and where and how to end it. You can first declare an integer variable and assign it the desired starting value. In the body of the while statement, visit each member of the list. If you are using an integer variable, you can increment it each time to move to the next value. Here is an example:
let mutable i = 0 let names = [ "Frank"; "James"; "Joshua"; "Mary" ] while i < names.Length do printfn "Name: %s" names.[i] i <- i + 1
A List in a List
In the lists we have created so far, we treated each item as a primitive type. In reality, each member of the list is considered a complete type and could be anything, including its own list.
To make a list a member of another list, in the placeholder of the list, create the list just as we have done so far, using its own square brackets. If you decide to use this technique, all list items must be the same type of list but they can have different numbers of items. Here is an example:
let names = [ ["Joshua"; "Morrison"]; ["Frank"; "Aaron"; "Xaviera"]; ["James"; "Lalong"] ]; printfn "%A" names;
To make the code easier to read, you can type the individual lists on their own lines. Here is an example:
let names = [ [ "Joshua"; "Morrison" ]; [ "Frank"; "Aaron"; "Xaviera" ]; [ "James"; "Lalong" ] ]
Operations on a List
Introduction
In the F# language, lists are represented by a module named List. The module is defined in the Microsoft.FSharp.Collections namespace (https://github.com/dotnet/fsharp/blob/main/src/FSharp.Core/list.fs). To provide some characteristics to a list, the Microsoft.FSharp.Collections namespace provides a generic union named List. This union is quipped with two constructors (operators) and various propertites.
An Empty List
We saw that, to create an empty list, you can assign empty square brackets [] to it. Alternatively, to let you create an empty list, the List module is equipped with a function named empty:
[<CompiledName("Empty")>] let empty<'T> = ([]: 'T list)
Here is an example of calling it and getting its value:
let noTenant = List.empty;
printfn "Tenants: %A" noTenant
After creating a list and while using it, at any time, to let you find out whether the list has no item, the List union is equipped with a Boolean property named IsEmpty:
[<CompiledName("IsEmpty")>] let isEmpty list = match list with | [] -> true | _ -> false
The Number of Items in a List
The number of items in a list is referred to as its length. To support it, the List union contains a property named Length. Its equivalent in the List module is the length() function. Its signature is:
List.length : 'T list -> int
As you can see, this function takes a list as argument and it returns an integer as the number of items in the list.
Getting an Item Based on Its Index
The items of a list are stored in a zero-based series. The first item occupies the 0 position. The second item occupies the 1 position, and so on. To let you get to an item based on its position+1 in the list, the List union is equipped with an indexed property named Item. Here is an example of using the property:
let numbers = [ 3 .. 2 .. 20 ]
printfn "Numbers: %A\n" numbers
let sixth = numbers.Item(5)
printfn "6th Member: %d\n" sixth
This would produce:
Numbers: [3; 5; 7; 9; 11; 13; 15; 17; 19]
6th Member: 13
Press any key to close this window . . .
In the same way, you can access any member of the list based on its position. Make sure you provide an index that is less than or equal to the number of items - 1. If you provide a number beyond the number of items, you will get an error.
Introductory Operations on Lists
Checking Whether a List is Empty
We know that, to create an empty list, you can assign empty square brackets [] to it. Here is an example:
let numbers = []
printfn "Numbers: %A" numbers
This would produce:
Numbers: [] Press any key to close this window . . .
To let you find out whether a list is empty, you can use the match operator with an option as []. If that option is valid, it means that the list is empty. The other option can be an underscore, which means that the list contains at least one item. Here are examples:
let numbers = [] let names = [ "Frank"; "James"; "Joshua"; "Mary" ] match numbers with | [] -> printfn "The list is empty" | _ -> printfn "Numbers: %A" numbers match names with | [] -> printfn "There is no name in the list" | _ -> printfn "Name: %A" names
This would produce:
The list is empty Name: ["Frank"; "James"; "Joshua"; "Mary"] Press any key to close this window . . .
As mentioned already, a list is immutable. Base on that, you can add (a) new item(s) to the list but you would get a new, different list, that contains the original item(s) and the new one(s). To let you perform this operation, the List union is equipped with, or defines, an operator as ::. To use it, start with the let operator and a new name, assign the new value to it, followed by :: and the original list. Here is an example:
let names = [ "Frank"; "James"; "Joshua"; "Mary" ]
printfn "%A" names
let additional = "Gabriel" :: names
printfn "%A" additional
This would produce:
[ "Frank"; "James"; "Joshua"; "Mary" ] [ "Gabriel"; "Frank"; "James"; "Joshua"; "Mary" ] Press any key to close this window . . .
Keep in mind that the original list has not changed:
// Names
let names = [ "Frank"; "James"; "Joshua"; "Mary" ]
printfn "%A" names
let additional = "Gabriel" :: names
printfn "%A" additional
printfn "%A" names
This would produce:
[ "Frank"; "James"; "Joshua"; "Mary" ]
[ "Gabriel"; "Frank"; "James"; "Joshua"; "Mary" ]
["Frank"; "James"; "Joshua"; "Mary" ]
Press any key to close this window . . .
Concatenating two list consists of adding them. To perform this operation, use the @ operator in place of +. The lists must be compatible. Here is an example:
let parents = [ "Frank"; "James"; "Joshua"; "Maryy" ]
let students = [ "Hermine"; "Sebastien"; "Lestery" ]
printfn "Parents: %A" parents
printfn "Students: %A" students
printfn "\nFamilies: %A" (parents @ students);
This would produce:
Parents: ["Frank"; "James"; "Joshua"; "Mary"]
Students: ["Hermine"; "Sebastien"; "Lester"]
Families: ["Frank"; "James"; "Joshua"; "Mary"; "Hermine"; "Sebastien"; "Lester"]
Press any key to close this window . . .
If you plan to use the result many times, you can store it in a variable. To do this, assign the concatenation to the variable. Here is an example:
let parents = [ "Frank"; "James"; "Joshua"; "Maryy" ]
let students = [ "Hermine"; "Sebastien"; "Lestery" ]
let families = parents @ students
printfn "Parents: %A" parents
printfn "Students: %A" students
printfn "Families: %A" families;
As an alternative to the @ operator, the List module provides a function named append. Its signature is
List.append : 'T list -> 'T list -> 'T list
This function takes two arguments that each is a list. The function returns a list. Here is an example of calling it:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
abstract member WeeklyTime : unit -> double
default this.WeeklyTime() = 40.00
abstract member WeeklySalary : unit -> double
default this.WeeklySalary() = salary
let fullTimeEmployeesPayrolls = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("5031-9259", EmploymentStatus.FullTime, 55000.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
let otherEmployeesPayrolls = [ Employee("9270-8039", EmploymentStatus.PartTime, 15800.00); Employee("2807-4083", EmploymentStatus.Seasonal, 22400.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00) ]
let payrollSummary = List.append fullTimeEmployeesPayrolls otherEmployeesPayrolls
printfn "Fixed Salaried Employee Payroll"
printfn "==================================="
printfn " Weekly \tYearly"
printfn "Empl # Time\tSalary"
printfn "-----------------------------------"
for payroll in payrollSummary do
printfn "%s %A\t%0.0f" payroll.EmployeeNumber payroll.EmploymentStatus (payroll.WeeklySalary())
printfn "===================================\n"
This would produce:
Fixed Salaried Employee Payroll =================================== Weekly Yearly Empl # Time Salary ----------------------------------- 9749-8075 FullTime 60000 2038-4051 FullTime 82000 5031-9259 FullTime 55000 7092-3094 FullTime 104000 2903-0481 FullTime 88500 5020-4681 FullTime 65200 9270-8039 PartTime 15800 2807-4083 Seasonal 22400 2405-8296 Seasonal 35400 2813-3044 PartTime 32500 =================================== Press any key to close this window . . .
Lists and Functions
Creating Items From a Function
Although each member of a list must be a constant value, each value can be created from a function. In the square brackets, call the function every time you need a value. If the function takes (a) parameter(s), make sure you pass the appropriate and necesary argument. Here is an example:
let multiply x = x * 2.27 let numbers = [ multiply 1.26; multiply 88.03; multiply 7.25; multiply 15.58 ] for n in numbers do printfn "Number: %0.04f" n
This would produce:
Number: 2.8602 Number: 199.8281 Number: 16.4575 Number: 35.3666 Press any key to close this window . . .
As an option, you can precede each function call with the yield keyword. Here is an example:
let multiply x = x * 2.27 let numbers = [ yield multiply 1.26; yield multiply 88.03; yield multiply 7.25; yield multiply 15.58 ] for n in numbers do printfn "Number: %0.04f" n
To add the values to the list, you can create a for loop that uses a range and calls the function to which you pass each value of the range. Here is an example:
let add x = x + x let numbers = [ for variable in 1 .. 8 -> add variable ] printfn "Numbers: %A" numbers
Remember that you can use do yield instead of ->. Here is an example:
let add x = x + x
let numbers = [ for variable in 1 .. 8 do yield add variable ]
printfn "Numbers: %A" numbers
This would produce:
Numbers: [2; 4; 6; 8; 10; 12; 14; 16] Press any key to close this window . . .
Of course, you can have a more complicated function than that. You can also generate values from the method of a class.
Returning a List from a Function
You can create a function that returns a list. To do this, make sure the last assignment of the function is a list. Here is an example:
let specifyWeeklyTime() =
[ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]
In other words, when a function has finished its assignment, you can make sure its last statement is a list. Here is an example:
let specifyWeeklyTime() =
let monday = 8.50
let tuesday = 9.50
let wednesday = 8.00
let thursday = 10.00
let friday = 9.00
let saturday = 0.00
let sunday = 0.00
[ monday; tuesday; wednesday; thursday; friday; saturday; sunday; ]
In fact, a function can simply return a variable as long as that variable represents a list. Here is an example:
let specifyWeeklyTime() =
let monday = 8.50
let tuesday = 9.50
let wednesday = 8.00
let thursday = 10.00
let friday = 9.00
let saturday = 0.00
let sunday = 0.00
let times = [ monday; tuesday; wednesday; thursday; friday; saturday; sunday; ]
times // The returned variable, a list
You can then use that returned value outside of the function. Here is an example:
let specifyWeeklyTime() =
[ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]
printfn "Weekly Time: %A" (specifyWeeklyTime())
You can also get the returned list and store it in a variable before using it. Here is an example:
let specifyWeeklyTime() =
[ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]
let times = specifyWeeklyTime()
printfn "Weekly Times: %A" times
This would produce:
Weekly Time: [8.5; 9.5; 8.0; 10.0; 9.0; 0.0; 0.0] Press any key to close this window . . .
Once you have a variable that holds a list, you can access each member of that list. Here is an example:
let specifyWeeklyTime() = [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00] let times = specifyWeeklyTime() for time in times do printfn "Time: %0.02f" time
This would produce:
Time: 8.50 Time: 9.50 Time: 8.00 Time: 10.00 Time: 9.00 Time: 0.00 Time: 0.00 Press any key to close this window . . .
Just like a function can return one list, it can return as many as you want. For example, you can create a function that returns a list of lists. Here is an example:
let specifyWeeklyTimes() = [ [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]; [ 6.00; 8.00; 9.00; 7.00; 8.00; 0.00; 0.00]; ] printfn "Weekly Time: %A\n" (specifyWeeklyTimes()) let times = specifyWeeklyTimes() for week in times do for time in week do printfn "Time: %0.02f" time
In the same way, you can return as many lists as you want.
A List as Parameter
A function can receive a parameter that is a list and treat it accordingly. Because F# is an inferred language, you can just pass the name of a parameter without a data type, and then use the parameter in the function as if that parameter were a list. Here is an example:
let displayWeeklyTimes(listOfTimes) = printfn "Weekly Time: %A" listOfTimes
Normally, at this time, the compiler doesn't know what type of parameter this is, and that parameter could be anything. When calling the function, pass a list as argument and the compiler will apply the appropriate rules based on the type of argument you passed. Here are examples:
let specifyWeeklyTime() = [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]; let displayWeeklyTimes(listOfTimes) = printfn "Weekly Time: %A" listOfTimes displayWeeklyTimes(specifyWeeklyTime()) printfn "--------------------------------------------------"
This would produce:
Weekly Time: [8.5; 9.5; 8.0; 10.0; 9.0; 0.0; 0.0] -------------------------------------------------- Press any key to close this window . . .
As mentioned already, when creating a function that takes a list as parameter, you can just specify a name for the parameter. Since you know that the parameter is a list, in the body of the function, treat the argument as a list, using all approriate rules of lists. For example, you can use a loop on the parameter. Here is an example:
let specifyWeeklyTime() = [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]; let displayWeeklyTimes(listOfTimes) = printfn "Weekly Time: %A" listOfTimes let times = specifyWeeklyTime() let showWeeklyTimes(listOfTimes) = for time in listOfTimes do printfn "Time: %0.02f" time displayWeeklyTimes(times) printfn "--------------------------------------------------" showWeeklyTimes(times) printfn "--------------------------------------------------"
This would produce:
Weekly Time: [8.5; 9.5; 8.0; 10.0; 9.0; 0.0; 0.0] -------------------------------------------------- Time: 8.50 Time: 9.50 Time: 8.00 Time: 10.00 Time: 9.00 Time: 0.00 Time: 0.00 -------------------------------------------------- Press any key to close this window . . .
In the same way, you can pass a parameter that is a list of lists (or a list of lists of lists...) and process it appropriately.
Lists and Tuples
Creating a Range From a Tuple
Lists are very important in functional programming. To enhance the functionalities of lists, the F# language provides various built-in operators and functions.
Tuples provide the ability to create a range from two members of a tuple:
When the .. operator is applied on both members, the result is a range that includes both values and the values between them. Here is an example:
let range(a, b) =
[a .. b];
let result = range(2, 8);
printfn "Values from a range: %A" result;
This would produce:
Values from a range: [2; 3; 4; 5; 6; 7; 8] Press any key to close this window . . .
You can also provide non-readable characters. In this case, the compiler would try to find their range. Here is an example:
let range(a, b) =
[a .. b];
let result = range('$', '*');
printfn "Values from a range: %A" result;
This would produce:
Values from a range: ['$'; '%'; '&'; '\''; '('; ')'; '*'] Press any key to close this window . . .
Either way, if the compiler cannot find values between both members of the tuple, in which case it cannot create a range, the compiler would produce an empty range [].
Creating a Skip Range From a Tuple
A skip range is a technique of specifying the starting value of a range, the end value of a range, and the value to add to each value to get the next one. You can get such a skip-range from a tuple. Here is an example:
let range(a, b, c) =
[a .. b .. c];
let result = range(2, 3, 16);
printfn "Values from a skip-range: %A" result;
This would produce:
Values from a skip-range: [2; 5; 8; 11; 14] Press any key to close this window . . .
A List of Tuples
You can create a list where each element is a tuple. Here is an example:
let timesWorked = [("Monday", 8.00); ("Tuesday", 9.00); ("Wednesday", 8.50); ("Thursday", 8.00); ("Friday", 8.50)]
You can then access the elements. For example, you can use %A to represent the list. Here is an example:
let timesWorked = [("Monday", 8.00); ("Tuesday", 9.00); ("Wednesday", 8.50); ("Thursday", 8.00); ("Friday", 8.50)] printfn "Times Worked: %A" timesWorked
This would produce:
Times Worked: [("Monday", 8.0); ("Tuesday", 9.0); ("Wednesday", 8.5); ("Thursday", 8.0); ("Friday", 8.5)] Press any key to close this window . . .
You can also use a for loop to access each tuple. Here is an example:
let timesWorked = [("Monday", 8.00); ("Tuesday", 9.00); ("Wednesday", 8.50); ("Thursday", 8.00); ("Friday", 8.50)] for t in timesWorked do printfn "Time Worked: %A" t
This would produce:
Time Worked: ("Monday", 8.0) Time Worked: ("Tuesday", 9.0) Time Worked: ("Wednesday", 8.5) Time Worked: ("Thursday", 8.0) Time Worked: ("Friday", 8.5) Press any key to close this window . . .
You can also use any technique of your choice to decompose the tuples and access their individual values. Here is an example:
let timesWorked = [("Monday", 8.00); ("Tuesday", 9.00); ("Wednesday", 8.50); ("Thursday", 8.00); ("Friday", 8.50)] printfn "Time Worked" printfn "-----------------" for t in timesWorked do let a, b = t printfn "%s: %0.02f" a b printfn "================="
This would produce:
Time Worked ----------------- Monday: 8.00 Tuesday: 9.00 Wednesday: 8.50 Thursday: 8.00 Friday: 8.50 ================= Press any key to close this window . . .
A Tuple of Lists
You can have a tuple whose elements are lists each. Here is an example:
let timesWorked = ([8.00; 9.00; 8.50; 8.00; 8.50], [8.50; 9.50; 8.00; 10.00; 9.00]) printfn "Work for 2 weeks: %A" timesWorked
This would produce:
Work for 2 weeks: ([8.0; 9.0; 8.5; 8.0; 8.5], [8.5; 9.5; 8.0; 10.0; 9.0]) Press any key to close this window . . .
You can then decompose the tuple to get each list. Here is an example:
let timesWorked = ([8.00; 9.00; 8.50; 8.00; 8.50], [8.50; 9.50; 8.00; 10.00; 9.00]) let a, b = timesWorked printfn "Work 1 time worked: %A" a printfn "Work 2 time worked: %A" b
This would produce:
Work 1 time worked: [8.0; 9.0; 8.5; 8.0; 8.5] Work 2 time worked: [8.5; 9.5; 8.0; 10.0; 9.0] Press any key to close this window . . .
To access the individual elements of each list, you have various options. You can use a for loop to visit each element of the list. Here are examples:
let timesWorked = ([8.00; 9.00; 8.50; 8.00; 8.50], [8.50; 9.50; 8.00; 10.00; 9.00]) let (a, b) = timesWorked printfn "Work 1 time worked" for t in a do printfn "%0.02f" t printfn "Work 2 time worked" for t in b do printfn "%0.02f" t
This would produce:
Work 1 time worked 8.00 9.00 8.50 8.00 8.50 Work 2 time worked 8.50 9.50 8.00 10.00 9.00 Press any key to close this window . . .
You can also store each list in a (temporary) variable. Here are examples:
let timesWorked = ([8.00; 9.00; 8.50; 8.00; 8.50], [8.50; 9.50; 8.00; 10.00; 9.00])
let (a, b) = timesWorked
let week1 = [for t in a do yield t]
let week2 = [for t in b do yield t]
printfn "Work 1 time worked: %A" week1
printfn "Work 2 time worked: %A" week2
This would produce:
Work 1 time worked: [8.0; 9.0; 8.5; 8.0; 8.5] Work 2 time worked: [8.5; 9.5; 8.0; 10.0; 9.0] Press any key to close this window . . .
Once you have each list, you can use it using any of the techniques and features of an F# list.
A List of Records
The members of a list can come from a record. You can first define a record, create objects from it, and use them as members of a list. Here is an example:
type OccupancyStatus = | Other = 0 | Available = 1 | Occupied = 2 | NeedsRepair = 3 type Apartment = { UnitNumber : string Bedrooms : int Bathrooms : float SecurityDeposit : int MonthlyRate : int Status : OccupancyStatus } let a399475 = { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available } let a508293 = { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair } let a729397 = { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
Instead of first creating the objects, you can add them directly in the list. Here is an example:
let apartments = [ { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available } { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair } { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available } { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied } { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available } ]
After doing this, you can access each member of the list as an individual record. Here is an example:
type OccupancyStatus = | Other = 0 | Available = 1 | Occupied = 2 | NeedsRepair = 3 type Apartment = { UnitNumber : string Bedrooms : int Bathrooms : float SecurityDeposit : int MonthlyRate : int Status : OccupancyStatus } let apartments = [ { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available } { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair } { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available } { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied } { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available } ] for apart in apartments do printfn "Apartment Record: %A" apart
This would produce:
Apartment Record: {UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.0; SecurityDeposit = 500; MonthlyRate = 950; Status = NeedsRepair;} Apartment Record: {UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.0; SecurityDeposit = 500; MonthlyRate = 925; Status = Available;} Apartment Record: {UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.0; SecurityDeposit = 850; MonthlyRate = 1350; Status = Occupied;} Apartment Record: {UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.0; SecurityDeposit = 550; MonthlyRate = 1150; Status = Available;} Press any key to close this window . . .
Or you can access each member of the record from the variable of the list. Here is an example:
type OccupancyStatus = | Other = 0 | Available = 1 | Occupied = 2 | NeedsRepair = 3 type Apartment = { UnitNumber : string Bedrooms : int Bathrooms : float SecurityDeposit : int MonthlyRate : int Status : OccupancyStatus } let apartments = [ { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available } { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair } { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available } { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied } { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available } ] printfn "=====================================================" printfn "\t\t\tMonthly" printfn "Unit # Beds\tBaths\tRent\tDeposit Status" printfn "-----------------------------------------------------" for apart in apartments do printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status printfn "-----------------------------------------------------"
This would produce:
===================================================== Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 101 2 2.00 1150 650 Available 102 1 1.00 950 500 NeedsRepair 103 1 1.00 925 500 Available 104 3 2.00 1350 850 Occupied 105 2 1.00 1150 550 Available ----------------------------------------------------- Press any key to close this window . . .
Lists and Classes
Objects as Members of a List
The members of a list can be anything, as long as all of them are of the same type. This means that you can use the basis for members of a list. Of course you must have a class. You can use one of the classes of the .NET Framework or you can create your own class. You can then create objects of your chosen class and use those objects as members of a list. Here is an example:
type Employee(emplNbr, salary, monday, tuesday, wednesday, thursday, friday, saturday, sunday) =
member val EmployeeNumber = emplNbr with get, set
member val HourlySalary = salary with get, set
member this.CalculateWeeklyTime() =
monday + tuesday + wednesday + thursday + friday + saturday + sunday
member this.CalculateWeeklySalary() =
salary * this.CalculateWeeklyTime()
let empl1 = Employee("2080-4813", 22.25, 8.50, 9.50, 8.00, 10.00, 9.00, 0.00, 0.00)
let empl2 = Employee("4029-3940", 26.88, 8.00, 8.00, 8.00, 8.00, 8.00, 0.00, 0.00)
let empl3 = Employee("8485-2082", 15.55, 6.50, 7.00, 8.00, 6.00, 7.00, 0.00, 0.00)
let empl4 = Employee("3924-8816", 34.52, 9.00, 8.50, 9.50, 9.50, 10.00, 0.00, 0.00)
let empl5 = Employee("1831-2039", 25.55, 8.00, 6.50, 6.00, 6.00, 7.50, 0.00, 0.00)
let employeesPayrolls = [ empl1; empl2; empl3; empl4; empl5 ];
Instead of first declaring individual variables, you can create the objects directly in the list. Here is an example:
let employeesPayrolls = [ Employee("2080-4813", 22.25, 8.50, 9.50, 8.00, 10.00, 9.00, 0.00, 0.00) Employee("4029-3940", 26.88, 8.00, 8.00, 8.00, 8.00, 8.00, 0.00, 0.00) Employee("8485-2082", 15.55, 6.50, 7.00, 8.00, 6.00, 7.00, 0.00, 0.00) Employee("3924-8816", 34.52, 9.00, 8.50, 9.50, 9.50, 10.00, 0.00, 0.00) Employee("1831-2039", 25.55, 8.00, 6.50, 6.00, 6.00, 7.50, 0.00, 0.00) ];
Either way, you can access the members of the class and use them as you see fit. Here is an example:
type Employee(emplNbr, salary, monday, tuesday, wednesday, thursday, friday, saturday, sunday) = member val EmployeeNumber = emplNbr with get, set member val HourlySalary = salary with get, set member this.CalculateWeeklyTime() = monday + tuesday + wednesday + thursday + friday + saturday + sunday member this.CalculateWeeklySalary() = salary * this.CalculateWeeklyTime() let empl1 = Employee("2080-4813", 22.25, 8.50, 9.50, 8.00, 10.00, 9.00, 0.00, 0.00) let empl2 = Employee("4029-3940", 26.88, 8.00, 8.00, 8.00, 8.00, 8.00, 0.00, 0.00) let empl3 = Employee("8485-2082", 15.55, 6.50, 7.00, 8.00, 6.00, 7.00, 0.00, 0.00) let empl4 = Employee("3924-8816", 34.52, 9.00, 8.50, 9.50, 9.50, 10.00, 0.00, 0.00) let empl5 = Employee("1831-2039", 25.55, 8.00, 6.50, 6.00, 6.00, 7.50, 0.00, 0.00) let employeesPayrolls = [ empl1; empl2; empl3; empl4; empl5 ]; printfn "Employee Payroll Summary" printfn "====================================================" printfn "Empl #\t\tSalary\tWeekly Time\tWeekly Salary" printfn "----------------------------------------------------" for empl in employeesPayrolls do printfn "%s\t%0.02f\t%0.02f\t\t%0.02F" empl.EmployeeNumber empl.HourlySalary (empl.CalculateWeeklyTime()) (empl.CalculateWeeklySalary()) printfn "===================================================="
This would produce:
Employee Payroll Summary ==================================================== Empl # Salary Weekly Time Weekly Salary ---------------------------------------------------- 2080-4813 22.25 45.00 1001.25 4029-3940 26.88 40.00 1075.20 8485-2082 15.55 34.50 536.48 3924-8816 34.52 46.50 1605.18 1831-2039 25.55 34.00 868.70 ==================================================== Press any key to close this window . . .
As mentioned already, all the members of a list must be of the same type. You can use objects of different classes in a list. The main rule is that the classes must share a common ancestry.
In the same way, you can create many lists using a class, or you can create different lists using classes of your choice. Here are examples:
type Employee(emplNbr, salary) = member this.EmployeeNumber = emplNbr abstract member WeeklyTime : unit -> double default this.WeeklyTime() = 40.00 abstract member WeeklySalary : unit -> double default this.WeeklySalary() = salary type Salaried(emplNbr, salary, monday, tuesday, wednesday, thursday, friday, saturday, sunday) = inherit Employee(emplNbr, salary) member val HourlySalary = salary with get, set override this.WeeklyTime() = monday + tuesday + wednesday + thursday + friday + saturday + sunday override this.WeeklySalary() = salary * this.WeeklyTime() let employeesPayrolls = [ Employee("9749-8075", 60000.00); Employee("2038-4051", 82000.00) ] let salariedPayrolls = [ Salaried("2080-4813", 22.25, 8.50, 9.50, 8.00, 10.00, 9.00, 0.00, 0.00) Salaried("4029-3940", 26.88, 8.00, 8.00, 8.00, 8.00, 8.00, 0.00, 0.00) Salaried("8485-2082", 15.55, 6.50, 7.00, 8.00, 6.00, 7.00, 0.00, 0.00) Salaried("3924-8816", 34.52, 9.00, 8.50, 9.50, 9.50, 10.00, 0.00, 0.00) Salaried("1831-2039", 25.55, 8.00, 6.50, 6.00, 6.00, 7.50, 0.00, 0.00) ]; printfn "Fixed Salaried Employee Payroll" printfn "====================================================" printfn " Weekly" printfn "Empl # Time Yearly Salary" printfn "----------------------------------------------------" for empls in employeesPayrolls do printfn "%s %0.0f %0.0f" empls.EmployeeNumber (empls.WeeklyTime()) (empls.WeeklySalary()) printfn "====================================================\n" printfn "Employee Payroll Summary" printfn "====================================================" printfn "Empl #\t\tSalary\tWeekly Time\tWeekly Salary" printfn "----------------------------------------------------" for empls in salariedPayrolls do printfn "%s\t%0.02f\t%0.02f\t\t%0.02F" empls.EmployeeNumber empls.HourlySalary (empls.WeeklyTime()) (empls.WeeklySalary()) printfn "===================================================="
This would produce:
Fixed Salaried Employee Payroll ==================================================== Weekly Empl # Time Yearly Salary ---------------------------------------------------- 9749-8075 40 60000 2038-4051 40 82000 ==================================================== Employee Payroll Summary ==================================================== Empl # Salary Weekly Time Weekly Salary ---------------------------------------------------- 2080-4813 22.25 45.00 1001.25 4029-3940 26.88 40.00 1075.20 8485-2082 15.55 34.50 536.48 3924-8816 34.52 46.50 1605.18 1831-2039 25.55 34.00 868.70 ==================================================== Press any key to close this window . . .
In the same way, you can create a list in a list (or a list in a list in a list...) or a list of lists (or a list of lists of lists...). Here is an example:
let employeesPayrolls = [ [ Employee("9749-8075", 60000.00); Employee("2038-4051", 82000.00) ] [ Salaried("2080-4813", 22.25, 8.50, 9.50, 8.00, 10.00, 9.00, 0.00, 0.00) Salaried("4029-3940", 26.88, 8.00, 8.00, 8.00, 8.00, 8.00, 0.00, 0.00) Salaried("8485-2082", 15.55, 6.50, 7.00, 8.00, 6.00, 7.00, 0.00, 0.00) Salaried("3924-8816", 34.52, 9.00, 8.50, 9.50, 9.50, 10.00, 0.00, 0.00) Salaried("1831-2039", 25.55, 8.00, 6.50, 6.00, 6.00, 7.50, 0.00, 0.00) ] ];
A List as a Property
A property of a class can be created from a list. We already know that a list can be passed to a function. This means that a parameter passed to the constructor of a class can represent a list. You can then use that parameter and assign it to a property. Here are examples:
type EmployeePayroll(emplNbr, name, salary, times) = member val EmployeeNumber = emplNbr with get, set member val FullName = name with get, set member val HourlySalary = salary with get, set member val WeeklyTimes = times with get, set
Once again, from these properties, the compiler doesn't know the data type of each parameter and a parameter can be anything. This also means that the compiler doesn't know whether a parameter is a list or not. When creating an object from the class, you can pass a list in the placeholder of an argument. Here are examples:
let ep = EmployeePayroll("2080-4813", [ "James"; "Roland"; "Alexanders" ], 22.25, [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00 ])
From that object, the compiler can infer the appropriate type of each parameter. You can then use each property as you see fit. Here are examples:
type EmployeePayroll(emplNbr, name, salary, times) = member val EmployeeNumber = emplNbr with get, set member val FullName = name with get, set member val HourlySalary = salary with get, set member val WeeklyTimes = times with get, set let ep = EmployeePayroll("2080-4813", [ "James"; "Roland"; "Alexanders" ], 22.25, [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00 ]) printfn "Employee Payroll Summary" printfn "----------------------------------------------------" printfn "Employee #: %s" ep.EmployeeNumber printfn "Full Name: %A" ep.FullName printfn "Hourly Salary: %0.02F" ep.HourlySalary printfn "Time Worked: %A" ep.WeeklyTimes printfn "----------------------------------------------------"
This would produce:
Employee Payroll Summary ---------------------------------------------------- Employee #: 2080-4813 Full Name: ["James"; "Roland"; "Alexanders"] Hourly Salary: 22.25 Time Worked: [8.5; 9.5; 8.0; 10.0; 9.0; 0.0; 0.0] ---------------------------------------------------- Press any key to close this window . . .
Remember that you can use a loop to access each member of a list. In the same way, once you have the value of a listed property, treat it as such. Here are examples:
type EmployeePayroll(emplNbr, name, salary, times) = member val EmployeeNumber = emplNbr with get, set member val FullName = name with get, set member val HourlySalary = salary with get, set member val WeeklyTimes = times with get, set let ep = EmployeePayroll("2080-4813", [ "James"; "Roland"; "Alexanders" ], 22.25, [ 8.50; 9.50; 8.00; 10.00; 9.00; 0.00; 0.00]) printfn "Employee Payroll Summary" printfn "----------------------------------------------------" printfn "Employee #: %s" ep.EmployeeNumber printf "Full Name: " for name in ep.FullName do printf "%s " name printfn "\nHourly Salary: %0.02F" ep.HourlySalary printf "Time Worked: " for time in ep.WeeklyTimes do printf "%0.02f " time printfn "\n----------------------------------------------------"
This would produce:
Employee Payroll Summary ---------------------------------------------------- Employee #: 2080-4813 Full Name: James Roland Alexanders Hourly Salary: 22.25 Time Worked: 8.50 9.50 8.00 10.00 9.00 0.00 0.00 ---------------------------------------------------- Press any key to close this window . . .
Operations on a List
Getting an Item Based on Its Index
As an alternative to the List.Item property, the List module is equipped with a static member function named nth. Its syntax is:
List.nth : 'T list -> int -> 'T
This function takes two arguments: a list variable and the index + 1 of the member you want to access. Here is an example of calling it:
let numbers = [3 .. 2 .. 20 ]
printfn "Numbers: %A\n" numbers
let sixth = List.nth numbers 5
printfn "6th Member: %d\n" sixth
Remember that the first item is located at index 0. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
abstract member WeeklyTime : unit -> double
default this.WeeklyTime() = 40.00
abstract member WeeklySalary : unit -> double
default this.WeeklySalary() = salary
let employeesPayrolls = [ Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
let payroll = List.tail employeesPayrolls
printfn "Fixed Salaried Employee Payroll"
printfn "==================================="
printfn " Weekly \tYearly"
printfn "Empl # Time\tSalary"
printfn "-----------------------------------"
for i = 0 to employeesPayrolls.Length - 1 do
printfn "%s %A\t%0.0f" (List.nth employeesPayrolls i).EmployeeNumber (List.nth employeesPayrolls i).EmploymentStatus ((List.nth employeesPayrolls i).WeeklySalary())
printfn "===================================\n"
This would produce:
Fixed Salaried Employee Payroll =================================== Weekly Yearly Empl # Time Salary ----------------------------------- 2405-8296 Seasonal 35400 2813-3044 PartTime 32500 2903-0481 FullTime 88500 5020-4681 FullTime 65200 =================================== Press any key to close this window . . .
Iterating Through a List
Iterating through a list consists of executing a function on each member of the list. One of the List functions used to perform this operation is called iter. Its signature is:
List.iter : ('T -> unit) -> 'T list -> unit
This function takes two arguments. The first is a function to use on each element. The second argument is a list. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
printfn "Fixed Salaried Employee Payroll"
printfn "==================================="
printfn " Employment \tYearly"
printfn "Empl # Status\tSalary"
printfn "-----------------------------------"
List.iter (fun (empl : Employee) -> printfn "%s %A\t%0.0f" empl.EmployeeNumber empl.EmploymentStatus empl.YearlySalary) employees
This would produce:
Fixed Salaried Employee Payroll =================================== Employment Yearly Empl # Status Salary ----------------------------------- 9749-8075 FullTime 60000 2038-4051 FullTime 82000 2405-8296 Seasonal 35400 2813-3044 PartTime 32500 2903-0481 FullTime 88500 5020-4681 FullTime 65200 Press any key to close this window . . .
The First Member of a List
To let you get the first member of a list, the List union provides a property named Head. Here is an example of using this property:
let numbers = [3 .. 2 .. 20 ]
printfn "Numbers: %A\n" numbers
let first = numbers.Head;
printfn "First Member: %d\n" first
This would produce:
Numbers: [3; 5; 7; 9; 11; 13; 15; 17; 19]
First Member: 3
Press any key to close this window . . .
To support this, the List module is equipped with a function named head. Its signature is:
List.head : 'T list -> 'T
Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
abstract member WeeklyTime : unit -> double
default this.WeeklyTime() = 40.00
abstract member WeeklySalary : unit -> double
default this.WeeklySalary() = salary
let employeesPayrolls = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00); ]
let payroll = List.head employeesPayrolls
printfn "Employee Payroll"
printfn "==================================="
printfn "Employee #: %s" payroll.EmployeeNumber
printfn "Status: %A" payroll.EmploymentStatus
printfn "Yearly Salary: %0.0f" (payroll.WeeklySalary())
printfn "===================================\n"
This would produce:
Employee Payroll =================================== Employee #: 9749-8075 Status: FullTime Yearly Salary: 60000 =================================== Press any key to close this window . . .
The Tail of a List
To let you get the list without the first item, the List union provides a property named Tail. Here is an example of using it:
let numbers = [3 .. 2 .. 20 ]
printfn "Numbers: %A\n" numbers
let freeOne = numbers.Tail
printfn "List without first member: %A\n" freeOne
This would produce:
Numbers: [3; 5; 7; 9; 11; 13; 15; 17; 19]
List without first member: [5; 7; 9; 11; 13; 15; 17; 19]
Press any key to close this window . . .
To support the tail of a list, the List module has a function named tail. Its signature is:
List.tail : 'T list -> 'T list
Remember that the tail in this case is the list of items from the argument but without the first element. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
abstract member WeeklyTime : unit -> double
default this.WeeklyTime() = 40.00
abstract member WeeklySalary : unit -> double
default this.WeeklySalary() = salary
let employeesPayrolls = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("5031-9259", EmploymentStatus.FullTime, 55000.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
let payroll = List.tail employeesPayrolls
printfn "Fixed Salaried Employee Payroll"
printfn "==================================="
printfn " Weekly \tYearly"
printfn "Empl # Time\tSalary"
printfn "-----------------------------------"
for pay in employeesPayrolls do
printfn "%s %A\t%0.0f" pay.EmployeeNumber pay.EmploymentStatus (pay.WeeklySalary())
printfn "===================================\n"
This would produce:
Fixed Salaried Employee Payroll =================================== Weekly Yearly Empl # Time Salary ----------------------------------- 9749-8075 FullTime 60000 2038-4051 FullTime 82000 5031-9259 FullTime 55000 7092-3094 FullTime 104000 2903-0481 FullTime 88500 5020-4681 FullTime 65200 =================================== Press any key to close this window . . .
The Last Member of a List
To get the last member of a list, you can call the List.Item property and pass the Length property - 1. Here is an example:
let numbers = [3 .. 2 .. 20 ]
printfn "Numbers: %A\n" numbers
let last = numbers.Item(numbers.Length - 1);
printfn "Last Member: %d\n" last
This would produce:
Numbers: [3; 5; 7; 9; 11; 13; 15; 17; 19]
Last Member: 19
Press any key to close this window . . .
Replacing the First Member of a List
The List union is equipped with a static method used to create a new list by specifying the first member of your choice and existing members from another list. The method is called Cons. Its signature is:
static member List.Cons : 'T * 'T list -> 'T list
This method takes two arguments and returns a list. The first argument is the value that will be used as the first in the new list. The second argument is the list to which the first argument will be added. Here is an example of calling it:
let numbers = [3 .. 2 .. 20 ]
printfn "Numbers: %A\n" numbers
let additional = List.Cons(228, numbers.Tail)
printfn "Numbers: %A\n" additional
This would produce:
Numbers: [3; 5; 7; 9; 11; 13; 15; 17; 19]
Numbers: [228; 5; 7; 9; 11; 13; 15; 17; 19]
Press any key to close this window . . .
If an Element Exists in a List
To let you find out whether a certain element exists in a list, the List module is equipped with a method named exists. Its signature is:
List.exists : ('T -> bool) -> 'T list -> bool
Here is an example of calling this method:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
abstract member WeeklyTime : unit -> double
default this.WeeklyTime() = 40.00
abstract member WeeklySalary : unit -> double
default this.WeeklySalary() = salary
let employeesPayrolls = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
let exists nbr list : bool = List.exists (fun (empl : Employee) -> empl.EmployeeNumber = nbr) list
let result = exists "2405-8296" employeesPayrolls
printfn "The employee exists: %b" result
This would produce:
The employee exists: true Press any key to close this window . . .
In our example, we defined a function. As an alternative, we could simply have provided the arguments when calling the List.exists() method:
let res = List.exists (fun (empl : Employee) -> empl.EmployeeNumber = "2405-8296") employeesPayrolls
To let you compare elements from two different lists by their corresponding positions, the List module provides a function named exists2. Its signature is:
List.exists2 : ('T1 -> 'T2 -> bool) -> 'T1 list -> 'T2 list -> bool
Applying a Condition to all Items
To let you apply a certain condition to all elements of a list, the List module is equipped with a function named forAll. Its signature is:
List.forall : ('T -> bool) -> 'T list -> bool
This function takes two arguments. The first arguments is a Boolean function to apply to the second argument. If at least one item of the list responds to the condition in the first argument, the function returns true. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("5031-9259", EmploymentStatus.FullTime, 55000.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00); ]
let areFullTimers = List.forall (fun (empl : Employee) -> empl.EmploymentStatus = EmploymentStatus.FullTime) employees;
printfn "Are all employees full-times? %b" areFullTimers
This would produce:
Are all employees full-times? true Press any key to close this window . . .
Here is another example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("5031-9259", EmploymentStatus.FullTime, 55000.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
let areFullTimers = List.forall (fun (empl : Employee) -> empl.EmploymentStatus = EmploymentStatus.FullTime) employees;
if areFullTimers = true then
printfn "Are all employees full-times? Yes"
else
printfn "Are all employees full-times? No"
This would produce:
Are all employees full-times? No Press any key to close this window . . .
Finding an Item in a List
To assist you with finding an item in a list, the List module provides a function named find. Its signature is:
List.find : ('T -> bool) -> 'T list -> 'T
Here are examples:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000); Employee("2038-4051", EmploymentStatus.FullTime, 82000);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400); Employee("2813-3044", EmploymentStatus.PartTime, 25500);
Employee("5031-9259", EmploymentStatus.FullTime, 25500); Employee("7092-3094", EmploymentStatus.FullTime, 104000); ]
let found = List.find (fun (empl : Employee) -> empl.EmployeeNumber = "2405-8296") employees
printfn "Employee Record"
printfn "==================================="
printfn "Employee #: %s" found.EmployeeNumber
printfn "Status: %A" found.EmploymentStatus
printfn "Yearly Salary: %i" found.YearlySalary
printfn "-----------------------------------"
This would produce:
Employee Record =================================== Employee #: 2405-8296 Status: Seasonal Yearly Salary: 35400 ----------------------------------- Press any key to close this window . . .
Picking an Item from a List
Picking an item from a list consists of applying a condition to it and selecting the first item that responds to that condition. To support this operation, the List module is equipped with a function named pick. Its signature is:
List.pick : ('T -> 'U option) -> 'T list -> 'U
This function takes two arguments. The first argument requires a matching condition and the second is the list that holds the items. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2928-7947", EmploymentStatus.PartTime, 30700.00);
Employee("2038-4051", EmploymentStatus.FullTime, 82000.00); Employee("5503-0485", EmploymentStatus.PartTime, 39580.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 15700.00);
Employee("5031-9259", EmploymentStatus.FullTime, 25500.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00); ]
let picker = List.pick (fun (empl : Employee) ->
match empl.EmploymentStatus with
| EmploymentStatus.PartTime -> Some(empl)
| _ -> None) employees
printfn "Employee Record"
printfn "==================================="
printfn "Employee #: %s" picker.EmployeeNumber
printfn "Status: %A" picker.EmploymentStatus
printfn "Yearly Salary: %0.0f" picker.YearlySalary
printfn "-----------------------------------"
This would produce:
Employee Record =================================== Employee #: 2928-7947 Status: PartTime Yearly Salary: 30700 ----------------------------------- Press any key to close this window . . .
Sub-Lists
Filtering by Some Items
A sub-list is a list derived from an existing list. To create a sub-list, you have many options.
To select some items from a list, you can apply a criterion that would filter some items, put them in a new list, and return that list. To support this operation, the List module provides a function named filter. Its signature is:
List.filter : ('T -> bool) -> 'T list -> 'T list
This function takes a function and a list as arguments. The internal function applies a condition to each item of the list. Every item that responds to the condition is put in a new list. At the end, that list is returned from the List.filter() function. Here is an example:
type OccupancyStatus =
| Other
| Available
| Occupied
| NeedsRepair
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = [
{ UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
{ UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
{ UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "106"; Bedrooms = 3; Bathrooms = 1.50; SecurityDeposit = 950; MonthlyRate = 1425; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "107"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.Occupied }
{ UnitNumber = "108"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Occupied }
]
let ready = List.filter (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Available) apartments
printfn "====================================================="
printfn "\t\t\tMonthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for apart in ready do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status
printfn "-----------------------------------------------------"
This would produce:
===================================================== Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 101 2 2.00 1150 650 Available 103 1 1.00 925 500 Available 105 2 1.00 1150 550 Available ----------------------------------------------------- Press any key to close this window . . .
Choosing a Sub-List
Choosing a sub-list consists of applying a criterion to an existing list. The elements that respond to the condition would be selected and added to the new list. To assist you with this, the List module is equipped with a function named choose. Its signature is:
List.choose : ('T -> 'U option) -> 'T list -> 'U list
This function takes two arguments. The first is a function that includes a matching conditional statement. The second argument is the list on which the condition will be applied. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
abstract member YearlySalary : unit -> double
default this.YearlySalary() = salary
let employeesPayrolls = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00);
Employee("2903-0481", EmploymentStatus.FullTime, 88500.00); Employee("5020-4681", EmploymentStatus.FullTime, 65200.00); ]
let choose = List.choose (fun (empl : Employee) ->
match empl.EmploymentStatus with
| EmploymentStatus.FullTime -> Some(empl)
| _ -> None) employeesPayrolls
printfn "Employees Salary Summary"
printfn "=============================="
printfn " \tYearly"
printfn "Empl # \tSalary"
printfn "------------------------------"
for i = 0 to choose.Length - 1 do
printfn "%s \t%0.0f" (List.nth choose i).EmployeeNumber ((List.nth choose i).YearlySalary())
printfn "==============================\n"
This would produce:
Employees Salary Summary ============================== Yearly Empl # Salary ------------------------------ 9749-8075 60000 2038-4051 82000 2903-0481 88500 5020-4681 65200 ============================== Press any key to close this window . . .
Mapping Some Elements
Mapping elements consists of applying a condition on each element of a list to select only the items that follow that condition to produce a new derived list. To let you perform this operation, the List module provides a function named map. Its signature is:
List.map : ('T -> 'U) -> 'T list -> 'U list
Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 15700.00);
Employee("5031-9259", EmploymentStatus.FullTime, 25500.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00); ]
let mapped = List.map (fun (empl : Employee) -> empl.YearlySalary) employees
printfn "Salaries: %A" mapped;
This would produce:
Salaries: [60000.0; 82000.0; 35400.0; 15700.0; 25500.0; 104000.0] ress any key to continue . . .
Partitioning a List
Particitioning a list consists of creating two lists derived from an existing one. To do this, you apply a condition to an existing list. The items that respond to the condition are put in a new list. The items that don't respond to the condition are put in another new list. To support this ôperation, the List module provides a function named partition. Its signature is:
List.partition : ('T -> bool) -> 'T list -> 'T list * 'T list
This function takes a function and a list as arguments. The function argument applies a condition to all members of the list. The function returns two lists. You can get the return value as two values or as a pair. Here is an example:
type OccupancyStatus =
| Other
| Available
| Occupied
| NeedsRepair
type Apartment = {
UnitNumber : string
Bedrooms : int
Bathrooms : float
SecurityDeposit : int
MonthlyRate : int
Status : OccupancyStatus }
let apartments = [
{ UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available }
{ UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied }
{ UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available }
{ UnitNumber = "106"; Bedrooms = 3; Bathrooms = 1.50; SecurityDeposit = 950; MonthlyRate = 1425; Status = OccupancyStatus.NeedsRepair }
{ UnitNumber = "107"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.Occupied }
{ UnitNumber = "108"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Occupied }
]
let (ready, not) = List.partition (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Available) apartments
printfn "====================================================="
printfn "Available Apartments"
printfn "\t\t\tMonthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for apart in ready do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status
printfn "-----------------------------------------------------"
printfn "====================================================="
printfn "Apartments not Available"
printfn "\t\t\tMonthly"
printfn "Unit # Beds\tBaths\tRent\tDeposit Status"
printfn "-----------------------------------------------------"
for apart in not do
printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status
printfn "-----------------------------------------------------"
This would produce:
===================================================== Available Apartments Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 101 2 2.00 1150 650 Available 103 1 1.00 925 500 Available 105 2 1.00 1150 550 Available ----------------------------------------------------- ===================================================== Apartments not Available Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 102 1 1.00 950 500 NeedsRepair 104 3 2.00 1350 850 Occupied 106 3 1.50 1425 950 NeedsRepair 107 1 1.00 950 500 Occupied 108 2 1.00 1150 550 Occupied ----------------------------------------------------- Press any key to close this window . . .
Notice that the List.partition() function returns a tuple pair whose two elements are a list each. If one of both tuple members holds a list whose members can be segmented based on certain criterion, you can call the function on that member to get another tuple with sub-lists. Here is an example:
type OccupancyStatus = | Other | Available | Occupied | NeedsRepair type Apartment = { UnitNumber : string Bedrooms : int Bathrooms : float SecurityDeposit : int MonthlyRate : int Status : OccupancyStatus } let apartments = [ { UnitNumber = "101"; Bedrooms = 2; Bathrooms = 2.00; SecurityDeposit = 650; MonthlyRate = 1150; Status = OccupancyStatus.Available } { UnitNumber = "102"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.NeedsRepair } { UnitNumber = "103"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 925; Status = OccupancyStatus.Available } { UnitNumber = "104"; Bedrooms = 3; Bathrooms = 2.00; SecurityDeposit = 850; MonthlyRate = 1350; Status = OccupancyStatus.Occupied } { UnitNumber = "105"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Available } { UnitNumber = "106"; Bedrooms = 3; Bathrooms = 1.50; SecurityDeposit = 950; MonthlyRate = 1425; Status = OccupancyStatus.NeedsRepair } { UnitNumber = "107"; Bedrooms = 1; Bathrooms = 1.00; SecurityDeposit = 500; MonthlyRate = 950; Status = OccupancyStatus.Occupied } { UnitNumber = "108"; Bedrooms = 2; Bathrooms = 1.00; SecurityDeposit = 550; MonthlyRate = 1150; Status = OccupancyStatus.Occupied } ] //let (ready, not) = List.partition (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Available) apartments let (notAvailable, available) = List.partition (fun (apart : Apartment) -> apart.Status <> OccupancyStatus.Available) apartments let (occupied, needsRepair) = List.partition (fun (apart : Apartment) -> apart.Status = OccupancyStatus.Occupied) notAvailable printfn "=====================================================" printfn "Available Apartments" printfn "\t\t\tMonthly" printfn "Unit # Beds\tBaths\tRent\tDeposit Status" printfn "-----------------------------------------------------" for apart in available do printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status printfn "-----------------------------------------------------" printfn "Occupied Apartments" printfn "\t\t\tMonthly" printfn "Unit # Beds\tBaths\tRent\tDeposit Status" printfn "-----------------------------------------------------" for apart in occupied do printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status printfn "-----------------------------------------------------" printfn "Apartments that need repair" printfn "\t\t\tMonthly" printfn "Unit # Beds\tBaths\tRent\tDeposit Status" printfn "-----------------------------------------------------" for apart in needsRepair do printfn "%s\t%i\t%.2f\t%d\t%d\t%A" apart.UnitNumber apart.Bedrooms apart.Bathrooms apart.MonthlyRate apart.SecurityDeposit apart.Status printfn "-----------------------------------------------------"
This would produce:
===================================================== Available Apartments Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 101 2 2.00 1150 650 Available 103 1 1.00 925 500 Available 105 2 1.00 1150 550 Available ----------------------------------------------------- Occupied Apartments Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 104 3 2.00 1350 850 Occupied 107 1 1.00 950 500 Occupied 108 2 1.00 1150 550 Occupied ----------------------------------------------------- Apartments that need repair Monthly Unit # Beds Baths Rent Deposit Status ----------------------------------------------------- 102 1 1.00 950 500 NeedsRepair 106 3 1.50 1425 950 NeedsRepair ----------------------------------------------------- Press any key to close this window . . .
Numeric Operations on Elements
The Sum of Values of a List
If you have a list made of numeric values, to let you get the sum of those values, the List module provides a function named sum. Its syntax is:
List.sum : ^T list -> ^T (requires ^T with static member (+) and ^T with static member Zero)
Here are examples:
let timesWorked = ([8.00; 9.00; 8.50; 8.00; 8.50], [8.50; 9.50; 8.00; 10.00; 9.00]) let (a, b) = timesWorked let week1 = [for t in a do yield t] let week2 = [for t in b do yield t] printfn "Work 1 time worked: %A\tTotal: %0.02f" week1 (List.sum week1) printfn "Work 2 time worked: %A\tTotal: %0.02f" week2 (List.sum week2)
This would produce:
Work 1 time worked: [8.0; 9.0; 8.5; 8.0; 8.5] Total: 42.00 Work 2 time worked: [8.5; 9.5; 8.0; 10.0; 9.0] Total: 45.00 Press any key to close this window . . .
The Average of a List
The List module supports various arithmetic operations on a list if the elements on that list are numbers.
The List.average() function is used to calculate the average of numbers. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 25500.00);
Employee("5031-9259", EmploymentStatus.FullTime, 25500.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00); ]
let salaries = [ for empl in employees -> empl.YearlySalary ]
let avgSalary = List.average salaries
printfn "Salaries: %A" salaries;
printfn "Average Salary: %0.0f" avgSalary;
This would produce:
Salaries: [60000.0; 82000.0; 35400.0; 25500.0; 25500.0; 104000.0] Average Salary: 55400 Press any key to close this window . . .
Sorting Items
Introduction
Sorting the items of a list consists of re-arranging them in order. If the items are of a primitive type, you can arrange them in alphabetical, numerical, or chronological order. If the items are based on a class, you must implement the IComparable interface that is equipped with a method named CompareTo.
To let you arrange the items of a list, the List module is equipped with a function named sort. Its signature is:
List.sort : 'T list -> 'T list
Here is an example:
open System; type EmploymentStatus = | Unknown = 0 | FullTime = 1 | PartTime = 2 | Intern = 3 | Seasonal = 4 type Employee(emplNbr, status, salary) = member this.EmployeeNumber = emplNbr member this.EmploymentStatus : EmploymentStatus = status member this.YearlySalary = salary interface IComparable with member this.CompareTo(obj : Object) = match obj with | :? Employee as empl -> compare this.YearlySalary empl.YearlySalary | _ -> 0 let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00); Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("2813-3044", EmploymentStatus.PartTime, 32500.00); Employee("5031-9259", EmploymentStatus.FullTime, 55000.00); Employee("7092-3094", EmploymentStatus.FullTime, 104000.00); ] let sorted = List.sort employees printfn "Employees Salary Summary" printfn "===================================" printfn " Employment \tYearly" printfn "Empl # Status\tSalary" printfn "-----------------------------------" List.iter (fun (empl : Employee) -> printfn "%s %A\t%0.0f" empl.EmployeeNumber empl.EmploymentStatus empl.YearlySalary) sorted
Sorting Items By a Condition
The List.sort() function is used to simply arrange all records of a list. If you want to apply a condition by which to sort records, you can use the sortBy() function of the List module. Its signature is:
List.sortBy : ('T -> 'Key) -> 'T list -> 'T list
This function takes two arguments. The first arguments specifies a condition by which to sort. Only the items that respond to the condition are sorted. The other items in their original positions. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, status, salary) =
member this.EmployeeNumber = emplNbr
member this.EmploymentStatus : EmploymentStatus = status
member this.YearlySalary = salary
let employees = [ Employee("9749-8075", EmploymentStatus.FullTime, 60000.00); Employee("2038-4051", EmploymentStatus.FullTime, 82000.00);
Employee("7092-3094", EmploymentStatus.FullTime, 104000.00); Employee("2813-3044", EmploymentStatus.PartTime, 25500.00);
Employee("2405-8296", EmploymentStatus.Seasonal, 35400.00); Employee("5031-9259", EmploymentStatus.FullTime, 18500.00); ]
let sorted = List.sortBy (fun (empl : Employee) -> empl.YearlySalary >= 60000.00) employees
printfn "Employees Records - Before Sorting"
printfn "==================================="
printfn " Employment \tYearly"
printfn "Empl # Status\tSalary"
printfn "-----------------------------------"
List.iter (fun (empl : Employee) -> printfn "%s %A\t%0.0f" empl.EmployeeNumber empl.EmploymentStatus empl.YearlySalary) employees
printfn "-----------------------------------"
printfn "Employees Records - Sorting Employees Whose Salary is >= 60,000"
printfn "==================================="
printfn " Employment \tYearly"
printfn "Empl # Status\tSalary"
printfn "-----------------------------------"
List.iter (fun (empl : Employee) -> printfn "%s %A\t%0.0f" empl.EmployeeNumber empl.EmploymentStatus empl.YearlySalary) sorted
printfn "-----------------------------------"
This would produce
Employees Records - Before Sorting =================================== Employment Yearly Empl # Status Salary ----------------------------------- 9749-8075 FullTime 60000 2038-4051 FullTime 82000 7092-3094 FullTime 104000 2813-3044 PartTime 25500 2405-8296 Seasonal 35400 5031-9259 FullTime 18500 ----------------------------------- Employees Records - Sorting Employees Whose Salary is >= 60,000 =================================== Employment Yearly Empl # Status Salary ----------------------------------- 2813-3044 PartTime 25500 2405-8296 Seasonal 35400 5031-9259 FullTime 18500 9749-8075 FullTime 60000 2038-4051 FullTime 82000 7092-3094 FullTime 104000 ----------------------------------- Press any key to close this window . . .
|
|||
Previous | Copyright © 2014-2024, FunctionX | Monday 06 November 2023 | Next |
|