
Sequences 

Fundamentals of Sequences



Imagine you want to count (positive) numbers in increment of
2 starting at 0. You would get 0, 2, 4, 6, 8, 10, 12, and so on. Imagine you
want to get negative numbers in decrement of 7 starting at 1. You would get
1, 8, 15, 22, 29, and so on. In mathematics, we refer to such lists as
series. In both of our cases, we have:

 A starting value
 A scheme to get the next number. In the first example, we incremented by
2 to
get the next value. In the second example, we decremented by 7 to get the next
value
 The list would never end. For our first example, the list goes up to infinity.
For our second example, the list goes down to
infinity. This means that it is practically impossible
to get or know the end value
In mathematics, the best or only way to represent a series
is by using an expression. For our example, the series would represent all x
natural numbers starting at 0 such that x = 2x.
Introduction to Sequences


A sequence is a series of values where the items follow a
logic. Because the members of a sequence follow a specific and known logic,
they must be:
Because you may not (or may never) get to the end of the
series, a sequence is usually used where a fixed number of items from a series
will be considered.
In F#, a sequence is created using the seq keyword
followed by curly brackets. The formula to follow is:
seq { body }
The body of the sequence defines its series of values. You
have many options.
A Sequence as a Range of Values


You can create a sequence as a range of values. Inside the curly brackets, use the formula:
StartValue .. EndValue
Here is an example:
seq { 0 .. 100 }
This would create the series as 0, 1, 2, 3, and so on.
Creating a Sequence from a Skip Range


You can also create a squence from a
skip range. To do this, inside the curly brackets, use the formula:
Start .. Step .. End
Here is an example:
seq { 0 .. 3 .. 100 }
This would create the series as 0, 3, 6, 9, and so on.
Creating a Sequence from a Loop


You
can create a sequence using a for loop/expression that indicates the
expression that the values of the series would follow. The basic formula is:
for VariableName in Range > body
The VariableName can be any lowercase letter or any
name. The
Range is usually specified in as Start Value .. End Value.
The body of the loop is created after the > sign. It can consist of and
expression that uses the
VariableName. Here is an example:
seq { for number in 0 .. 100 > 2 * number + 1 }
An alternative to the > operator is to use the do yield expression.
Here is an example:
seq { for number in 0 .. 100 do yield 2 * number + 1 }
To be able to refer to a squence many times in your program,
you should store it in a variable. This is done by let binding it to a variable.
Here are examples:
let numbers = seq { 0 .. 100 };
let interestRates = seq { 8.25 .. 0.25 .. 16.75 };
let evens = seq { for nbr in 0 .. 50 > 2 * nbr };
Accessing the Whole Sequence


To display the values of a sequence in the printf() or the printfn() function,
use %A in the placeholder. Here are examples:
printfn "Numbers %A" (seq { 0 .. 100 });
printfn "Numbers %A" (seq { 0 .. 3 .. 100 })
printfn "Numbers %A" (seq { for number in 0 .. 100 > 2 * number + 1 })
These would produce:
Numbers seq [0; 1; 2; 3; ...]
Numbers seq [0; 3; 6; 9; ...]
Numbers seq [1; 3; 5; 7; ...]
Press any key to continue . . .
If the sequence is stored in a variable, use its name to access it. Here are examples:
let numbers = seq { 0 .. 100 };
let interestRates = seq { 8.25 .. 0.25 .. 16.75 };
let evens = seq { for nbr in 0 .. 50 > 2 * nbr };
printfn "Simple Numbers: %A" numbers;
printfn "Interest Rates: %A" interestRates;
printfn "Even Numbers: %A" evens;
This would produce:
Simple Numbers: seq [0; 1; 2; 3; ...]
Interest Rates: seq [8.25; 8.5; 8.75; 9.0; ...]
Even Numbers: seq [0; 2; 4; 6; ...]
Press any key to continue . . .
To access each value of a sequence, you can use a for loop
whose variable would represent each individual item. Since all members are of
the same type, you can use the appropriate character in the placeholder of the printf() or the printfn() function. Here is an example:
let numbers = seq { 1 .. 10 };
for i in numbers do
printfn "Number: %d" i;
This would produce:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
Number: 6
Number: 7
Number: 8
Number: 9
Number: 10
Press any key to continue . . .
Of course, you can include any conditional statement(s) in
the loop section. Here is an example:
let numbers = seq { 1 .. 10 };
for i in numbers do
if i % 2 <> 0 then
printfn "Number: %d" i;
This would produce:
Number: 1
Number: 3
Number: 5
Number: 7
Number: 9
Press any key to continue . . .
Creating and Returning a Sequence


You can have a function that returns a sequence. The simplest way is to have a function that creates a
sequence and returns it. The function can return a regular list of values or a sequence created using a for loop that
includes an expression. For example, in linear geometry, we learn that, to plot a line, we use an equation as:
y = ax + b
To use such a function, we can first choose a function such as 2x  y = 1 that can be converted to
y = 2x  1 and then to y = 2x + 1. Then, to calculate the value of y, we can pass the value of x to a function as follows:
let getYGraphValue y = (2 * x) + 1
We can use such an expression in a sequence and let the function return a (partial) sequence of values.
Here is an example:
let generateGraphValues() = seq { for i in 2 .. 2 > (2 * i) + 1 }
let line = generateGraphValues()
printfn "Values: %A" line
This would produce:
Values: seq [3; 1; 1; 3; ...]
Press any key to continue . . .
You can also have a function that takes arguments of any type and return a sequence. Here is an example:
let generateGraphValues a b = seq { for i in 2 .. 2 > (a * i) + b }
let line = generateGraphValues 2 8 // 2x + y = 8 => y = 2x + 8
printfn "Values: %A" line
This would produce:
Values: seq [12; 10; 8; 6; ...]
Press any key to continue . . .
Passing a Sequence as Argument


A function can receive a sequence as parameter and use it in its body. At a minimum, a function can simply display
the values of the sequence. Here is an example:
let generateGraphValues a b = seq { for i in 2 .. 2 > (a * i) + b }
let showValues values =
for v in values do printfn "%i" v
let line = generateGraphValues 2 8 // 2x + y = 8 => y = 2x + 8
showValues line;
This would produce:
12
10
8
6
4
Press any key to continue . . .
A sequence of tuples is a sequence where each element is a tuple, which can be a pair, a triple, or else.
Such a sequence is in the form:
seq { (...); (...); ... }
To create the sequence, you can generate the values for each tuple using an expression through a for loop
of a sequence. Make sure you provide the appropriate items for each tuple. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
let points = generateGraphValues 2 6
printfn "Values: %A" points
This would produce:
Values: seq [(4, 2); (3, 0); (2, 2); (1, 4); ...]
Press any key to continue . . .
Notice that the result includes only the first four elements of the sequence. If you want to show all possible
tuples from the sequence, you can access each one of them using a for loop. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
let points = generateGraphValues 2 6
printfn "Points by which the line passes:"
do
for pt in points do printf "%A " pt
This would produce:
Points by which the line passes:
(4, 2) (3, 0) (2, 2) (1, 4) (0, 6) (1, 8) (2, 10) (3, 12) (4, 14)
Press any key to continue . . .
Remember that you can pass a sequence to a function. You can then use the sequence in the body of the function however
you want. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
let showPoints sequence =
let mutable c : int = 65;
for pt in sequence do
printfn "%c%A" (char c) pt
c < c + 1
let points = generateGraphValues 2 6
printfn "Points by which the line passes:"
showPoints points
This would produce:
Points by which the line passes:
A(4, 2)
B(3, 0)
C(2, 2)
D(1, 4)
E(0, 6)
F(1, 8)
G(2, 10)
H(3, 12)
I(4, 14)
Press any key to continue . . .
You can use a tuple that holds some values and extract a sequence from those values. In the same way,
you can use two or more tuples and generate a sequence from them. Consider an equation of a line:
ax + by = c
Imagine you are given two points P and Q by which the line passes. Each point has coordinates for
the horizontal axis x and for the vertical axis y. We can denote them as a and b. We can then consider the points as:
P(a1, b1)
Q(a2, b2)
To calculate the slope of the line, we can use the formula:
b2  b1
m = 
a2  a1
Once we have the slope, we can deduce the equation of the line as:
y  b1 = m(x  a1)
Which is the same as:
y  b1 = mx  ma1
We can then perform the necessary substitions to calculate y:
ax + by = c => a1, a2, b1, b2 => P(a1, b1), Q(a2, b2)
b2  b1
m = 
a2  a1
y  b1 = m(x  a1)
y  b1 = mx  ma1
mx + y = ma1 + b1
b2  b1 b2  b1
x() + y = a1() + b1
a2  a1 a2  a1
b2x  b1x a1b2 + a1b1
 + y =  + b1
a2  a1 a2  a1
b1x  b2x a1b1  a1b2
 + y =  + b1
a2  a1 a2  a1
(b1  b2)x a1b1  a1b2
 + y =  + b1
a2  a1 a2  a1
(b1  b2)x (a2  a1)y a1b1  a1b2 (a2  a1)b1
 +  =  + 
a2  a1 a2  a1 a2  a1 a2  a1
(b1  b2)x + (a2  a1)y = a1b1  a1b2 + (a2  a1)b1
(b1  b2)x + (a2  a1)y = a1b1  a1b2 + a2b1  a1b1
(b1  b2)x + (a2  a1)y = a1b1  a1b1  a1b2 + a2b1
(b1  b2)x + (a2  a1)y = a2b1  a1b2
(b1  b2)x + (a2  a1)y = a2b1  a1b2
(a2  a1)y = a2b1  a1b2  (b1  b2)x
a2b1  a1b2  (b1  b2)x
y = 
(a2  a1)
a2b1  a1b2  b1x + b2x
y = 
(a2  a1)
Based on this, you can provide two tuples that hold two point coordinates by which a line passes, and then generate a
sequence of points by which the line passes. Here is an example:
let generatePoints (a1, b1) (a2, b2) =
// (a1, b1) = Possible first point from which the line passes
// (a2, b2) = Possible second point from which the line passes
// With an equation as
// y = ((a2 * b1)  (a1 * b2)  (b1 * x) + (b2 * x)) / (a2  a1)
// we can generate a sequence of pairs from 0 to 5
seq { for n = 0 to 5 do yield (n, ((a2 * b1)  (a1 * b2)  (b1 * n) + (b2 * n)) / (a2  a1)) }
let points = generatePoints (1, 6) (3, 2)
printfn "Points by which the line passes: %A" points
This would produce:
Points by which the line passes: seq [(0, 8); (1, 6); (2, 4); (3, 2); ...]
Press any key to continue . . .
Notice that the result includes only the first four members. If you want to show all resulting tuples, you can access each
member of the sequence using a for loop. Here is an example:
let generatePoints (a1, b1) (a2, b2) =
// (a1, b1) = Possible first point from which the line passes
// (a2, b2) = Possible second point from which the line passes
// With an equation as
// y = ((a2 * b1)  (a1 * b2)  (b1 * x) + (b2 * x)) / (a2  a1)
// we can generate a sequence of pairs from 0 to 5
seq { for n = 0 to 5 do yield (n, ((a2 * b1)  (a1 * b2)  (b1 * n) + (b2 * n)) / (a2  a1)) }
let points = generatePoints (1, 6) (3, 2)
printf "The line passes by the following points:"
for t in points do printf "%A, " t
printfn ""
This would produce:
The line passes by the following points:(0, 8), (1, 6), (2, 4), (3, 2), (4, 0), (5, 2),
Press any key to continue . . .
Since we used a function in this case, you can pass (a) tupple(s) and other (types of) parameters any way you want. Here is an example:
let generatePoints (a1, b1) (a2, b2) start finish =
// (a1, b1) = Possible first point from which the line passes
// (a2, b2) = Possible second point from which the line passes
// With an equation as
// y = ((a2 * b1)  (a1 * b2)  (b1 * x) + (b2 * x)) / (a2  a1)
// we can generate a sequence of pairs from 0 to 5
seq { for n = start to finish do yield (n, ((a2 * b1)  (a1 * b2)  (b1 * n) + (b2 * n)) / (a2  a1)) }
let points = generatePoints (2, 3) (3, 8) 2 3
printf "The line passes by the following points:"
for t in points do printf "%A, " t
printfn ""
This would produce:
The line passes by the following points:(2, 3), (1, 4), (0, 5), (1, 6), (2, 7), (3, 8),
Press any key to continue . . .
The members of a tuple can be a sequence each. You can use existing (or already created) sequences and add them in the parentheses
of a tuple. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
let line1 = generateGraphValues 2 6
let line2 = generateGraphValues 3 2
(line1, line2)
Or you can create the sequence directly in the parentheses of the tuple. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
(generateGraphValues 2 6, generateGraphValues 3 2)
Either way, once the tuple exists, you can use it. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
printfn "Points: %A" (generateGraphValues 2 6, generateGraphValues 3 2)
This would produce:
Points: (seq [(4, 2); (3, 0); (2, 2); (1, 4); ...],
seq [(4, 10); (3, 7); (2, 4); (1, 1); ...])
Press any key to continue . . .
If you want to use the tuple many times, you should store it in a variable. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4 .. 4 > (i, (a * i) + b) }
let lines = (generateGraphValues 2 6, generateGraphValues 3 2)
printfn "Points: %A" lines
If you want to individually identify the members of the tuple, you can create a name for each and use that name
when necessary. Here is an example:
let generateGraphValues a b = // y = ax + b
seq { for i in 4.00 .. 4.00 > (i, (a * i) + b) }
let (line1, line2, line3) = (generateGraphValues 2.00 6.00,
generateGraphValues 3.00 2.00,
generateGraphValues 0.50 2.00)
printfn "Line 1: %A" line1
printfn "Line 2: %A" line2
printfn "Line 3: %A" line3
This would produce:
Line 1: seq [(4.0, 2.0); (3.0, 0.0); (2.0, 2.0); (1.0, 4.0); ...]
Line 2: seq [(4.0, 10.0); (3.0, 7.0); (2.0, 4.0); (1.0, 1.0); ...]
Line 3: seq [(4.0, 0.0); (3.0, 0.5); (2.0, 1.0); (1.0, 1.5); ...]
Press any key to continue . . .
Sequences and Classes/Structures


The members of a sequence can be objects from a structure or a class. Of course, you must first decide what structure to use. You can
use one of the structures from the .NET Framework or you can create your own structure. You can then use it to generate the values of the
sequence. For example, you can use a value, such as one from a primitive type, in a for loop of a sequence, build an object from there, and make
it a member of a sequence. Here is an example:
type Point(x : int, y : int) =
let mutable ptX = x;
let mutable ptY = y;
member me.X with get() : int = ptX and set(value : int) = ptX < value;
member me.Y with get() : int = ptY and set(value : int) = ptY < value;
let generateGraphPoints a b = // y = ax + b
seq { for i in 4 .. 4 > new Point(i, (a * i) + b) }
You must provide a way to access each member of the sequence. One way you can do this is to create a method that can expose the
object. Here is an example:
type Point(x : int, y : int) =
let mutable ptX = x;
let mutable ptY = y;
member me.X with get() : int = ptX and set(value : int) = ptX < x;
member me.Y with get() : int = ptY and set(value : int) = ptY < y;
member me.Expression() = "P(" + (string ptX) + ", " + (string ptY) + ")"
let generateGraphPoints a b = // y = ax + b
seq { for i in 4 .. 4 > new Point(i, (a * i) + b) }
let points = generateGraphPoints 3 2
printfn "Points by which the line passes"
for pt in points do printfn "\t\t%s" (pt.Expression())
This would produce:
Points by which the line passes
P(4, 10)
P(3, 7)
P(2, 4)
P(1, 1)
P(0, 2)
P(1, 5)
P(2, 8)
P(3, 11)
P(4, 14)
Press any key to continue . . .
In the above example, we passed two integers to a function and used them to pass two arguments to the constructor of a
class. In the same way, you can pass one or more objects to a function that would use it/them to create a sequence of objects. Here is an example
where a function receives two points created each from a class. The function uses the members of that object to create a tuple. A series of the
resulting tuples is used as members of a sequence:
type Point(x : int, y : int) =
let mutable ptX = x;
let mutable ptY = y;
member me.X with get() : int = ptX and set(value : int) = ptX < x;
member me.Y with get() : int = ptY and set(value : int) = ptY < y;
let pt = new Point(1, 6);
printfn "P(%i, %i)" pt.X pt.Y
let generatePoints (P : Point) (Q : Point) =
// P = One of the points by which the line passes
// Q = Another point by which the line passes
seq { for n = 0 to 5 do yield (n, ((Q.X * P.Y)  (P.X * Q.Y)  (P.X * n) + (Q.Y * n)) / (Q.X  P.X)) }
let points = generatePoints (Point(2, 3)) (Point(3, 8))
printfn "Points by which the line passes"
for pt in points do printfn "\t\t%A" pt
This would produce:
Points by which the line passes
(0, 5)
(1, 7)
(2, 9)
(3, 11)
(4, 13)
(5, 15)
Press any key to continue . . .
A Sequence as a Member of a Class


A member of a class or structure can be a sequence. This
means that a property can be a sequence. When creating the property, you can use
the getter to specify how the property will get its sequencial values. Here is
an example of a class with two sequencebased properties:
type SystemOfEquations (line1 : Line, line2 : Line) =
let mutable l1 = line1;
let mutable l2 = line2;
member this.Line1 with get() : Line = l1 and set(value : Line) = l1 < value;
member this.Line2 with get() : Line = l2 and set(value : Line) = l2 < value;
member this.Points1 with get() = seq { for i in 2.00 .. 2.00 > (l1.Point1.X * i) + l1.Point1.Y }
member this.Points2 with get() = seq { for i in 2.00 .. 2.00 > (l2.Point1.X * i) + l2.Point1.Y }
You can then access the property outside the class just as
you would any other property.
Here is an example:
type Point(x : float, y : float) =
let mutable ptX = x;
let mutable ptY = y;
member me.X with get() : float = ptX and set(value : float) = ptX < value;
member me.Y with get() : float = ptY and set(value : float) = ptY < value;
member me.Expression() = "P(" + (string ptX) + ", " + (string ptY) + ")"
type Line(pt1 : Point, pt2 : Point) =
let mutable ptX = pt1;
let mutable ptY = pt2;
member self.Point1 with get() : Point = ptX and set(value : Point) = ptX < value;
member self.Point2 with get() : Point = ptY and set(value : Point) = ptY < value;
// member self.Length ...
type SystemOfEquations (line1 : Line, line2 : Line) =
let mutable l1 = line1;
let mutable l2 = line2;
member this.Line1 with get() : Line = l1 and set(value : Line) = l1 < value;
member this.Line2 with get() : Line = l2 and set(value : Line) = l2 < value;
member this.Points1 with get() = seq { for i in 2.00 .. 2.00 > (l1.Point1.X * i) + l1.Point1.Y }
member this.Points2 with get() = seq { for i in 2.00 .. 2.00 > (l2.Point1.X * i) + l2.Point1.Y }
member this.Relationship() : string =
let m1 : float = (l1.Point1.Y  l1.Point2.Y) / (l1.Point2.X  l1.Point1.X)
let m2 : float = (l2.Point1.Y  l2.Point2.Y) / (l2.Point2.X  l2.Point1.X)
if m1 = m2 then
"Lines are parallel"
elif (((l1.Point1.Y  l1.Point2.Y) / (l1.Point2.X  l1.Point1.X)) * ((l2.Point1.Y  l2.Point2.Y) / (l2.Point2.X  l2.Point1.X))) = 1.000000 then
"Lines are perpendicular"
else
"Lines are neither parallel nor perpendicular"
(*let p1 = Point(1.00, 2.00);
let p2 = Point( 1.00, 2.00);
let p3 = Point(2.00, 0.00);
let p4 = Point( 0.00, 4.00);
let p1 = Point( 0.00, 4.00);
let p2 = Point(1.00, 7.00);
let p3 = Point( 3.00, 0.00);
let p4 = Point(3.00, 2.00);
let p1 = Point(4.00, 2.00);
let p2 = Point( 0.00, 3.00);
let p3 = Point(3.00, 2.00);
let p4 = Point( 3.00, 2.00);
let line1 = Line(p1, p2);
let line2 = Line(p3, p4);
let soe = SystemOfEquations(line1, line2);*)
let soe1 = SystemOfEquations(Line(Point(1.00, 2.00), Point( 1.00, 2.00)), Line(Point(2.00, 0.00), Point( 0.00, 4.00)));
let soe2 = SystemOfEquations(Line(Point( 0.00, 4.00), Point(1.00, 7.00)), Line(Point( 3.00, 0.00), Point(3.00, 2.00)));
let soe3 = SystemOfEquations(Line(Point(4.00, 2.00), Point( 0.00, 3.00)), Line(Point(3.00, 2.00), Point( 3.00, 2.00)));
printfn "System of Equations 1 __________________________"
printfn "Line 1 from (1.00, 2.00) to ( 1.00, 2.00): %A" soe1.Points1
printfn "Line 2 from (2.00, 0.00) to ( 0.00, 4.00): %A" soe1.Points2
printfn "Relationship: %s" (soe1.Relationship())
printfn "==============================================================================="
printfn "System of Equations 2 __________________________"
printfn "Line 1 from ( 0.00, 4.00) to (1.00, 7.00): %A" soe2.Points1
printfn "Line 2 from ( 3.00, 0.00) to (3.00, 2.00): %A" soe2.Points2
printfn "Relationship: %s" (soe2.Relationship())
printfn "==============================================================================="
printfn "System of Equations 3 __________________________"
printfn "Line 1 from (4.00, 2.00) to ( 0.00, 3.00): %A" soe3.Points1
printfn "Line 2 from (3.00, 2.00) to ( 3.00, 2.00): %A" soe3.Points2
printfn "Relationship: %s" (soe3.Relationship())
printfn "==============================================================================="
This would produce:
System of Equations 1 __________________________
Line 1 from (1.00, 2.00) to ( 1.00, 2.00): seq [0.0; 1.0; 2.0; 3.0; ...]
Line 2 from (2.00, 0.00) to ( 0.00, 4.00): seq [4.0; 2.0; 0.0; 2.0; ...]
Relationship: Lines are parallel
===============================================================================
System of Equations 2 __________________________
Line 1 from ( 0.00, 4.00) to (1.00, 7.00): seq [4.0; 4.0; 4.0; 4.0; ...]
Line 2 from ( 3.00, 0.00) to (3.00, 2.00): seq [6.0; 3.0; 0.0; 3.0; ...]
Relationship: Lines are perpendicular
===============================================================================
System of Equations 3 __________________________
Line 1 from (4.00, 2.00) to ( 0.00, 3.00): seq [10.0; 6.0; 2.0; 2.0; ...]
Line 2 from (3.00, 2.00) to ( 3.00, 2.00): seq [4.0; 1.0; 2.0; 5.0; ...]
Relationship: Lines are neither parallel nor perpendicular
===============================================================================
Press any key to continue . . .
