Adding Overloaded Constructors to Implicit F# Type - f#

I have created the following type using implicit type construction:
open System
type Matrix(sourceMatrix:double[,]) =
let rows = sourceMatrix.GetUpperBound(0) + 1
let cols = sourceMatrix.GetUpperBound(1) + 1
let matrix = Array2D.zeroCreate<double> rows cols
do
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
matrix.[i,j] <- sourceMatrix.[i,j]
//Properties
///The number of Rows in this Matrix.
member this.Rows = rows
///The number of Columns in this Matrix.
member this.Cols = cols
///Indexed Property for this matrix.
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value =
this.Validate(x,y)
matrix.[x, y] <- value
//Methods
/// Validate that the specified row and column are inside of the range of the matrix.
member this.Validate(row, col) =
if(row >= this.Rows || row < 0) then raise (new ArgumentOutOfRangeException("row is out of range"))
if(col >= this.Cols || col < 0) then raise (new ArgumentOutOfRangeException("column is out of range"))
However now I need to add the following overloaded constructor to this type (which is in C# here):
public Matrix(int rows, int cols)
{
this.matrix = new double[rows, cols];
}
The problem that I have is that it seems any overloaded constructors in an implicit type must have a parameter list that is a subset of the first constructor. Obviously the constructor I want to add does not meet this requirement. Is there any way to do this using implicit type construction? Which way should I do this? I'm pretty new to F# so if you could show the whole type with your changes in it I would greatly appreciate it.
Thanks in advance,
Bob
P.S. If you have any other suggestions to make my class more in the functional style please feel free to comment on that as well.

I would probably just do this:
type Matrix(sourceMatrix:double[,]) =
let matrix = Array2D.copy sourceMatrix
let rows = (matrix.GetUpperBound 0) + 1
let cols = (matrix.GetUpperBound 1) + 1
new(rows, cols) = Matrix( Array2D.zeroCreate rows cols )
unless we are talking about very large arrays which are created very often (i.e. copying the empty array becomes a performance bottleneck).
If you want to emulate the C# version, you need an explicit field that can be accessed from both constructors, like so:
type Matrix(rows,cols) as this =
[<DefaultValue>]
val mutable matrix : double[,]
do this.matrix <- Array2D.zeroCreate rows cols
new(source:double[,]) as this =
let rows = source.GetUpperBound(0) + 1
let cols = source.GetUpperBound(1) + 1
Matrix(rows, cols)
then
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
this.matrix.[i,j] <- source.[i,j]
BTW, there is also a matrix type in the F# PowerPack.

Related

Is there a way to return a pair of integers using the let construct in standard ML?

I am trying to return a pair of sums using the let construct in sml. Every way I have tried will only return one value. I have tried creating a list by using cons (::) and then returning the list, but that gives an error as well.
val t = [(3,4), (4,5), (5,6)];
fun sumPairs(nil) = 0
| sumPairs((x,y)::zs) =
let
val sumFirst = x + sumPairs(zs)
val sumSecond = y + sumPairs(zs)
in
(sumFirst, sumSecond) <how would I return this as a tuple or list?>
end;
sumPairs(t);
The problem is not with (sumFirst, sumSecond) or with let specifically, but with the rest of your code.
The base case and the recursions say that sumPairs produces an int, not a pair of ints.
Because of this, there is a conflict when you try produce a pair.
Your base case should be (0,0), not 0, since it must be a pair.
You also need to deconstruct the result from the recursion since that produces a pair, not an integer.
Like this
fun sumPairs nil = (0, 0)
| sumPairs ((x,y)::zs) =
let
val (sumFirst, sumSecond) = sumPairs zs
in
(x + sumFirst, y + sumSecond)
end;

Swift Range Operator with two unknown values

If I have two unknown values, lets say x and y, what is the best way loop through all of the values between between those values?
For example, given the values x = 0 and y = 5 I would like to do something with the values 0, 1, 2, 3, 4, and 5. The result could exclude 0 and 5 if this is simpler.
Using Swift's Range operator, I could do something like this:
for i in x...y {
// Do something with i
}
Except I do not know if x or y is the greater value.
The Swift documentation for Range Operators states:
The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.
There are a number of solutions here. A pretty straight forward one is:
let diff = y - x
for i in 0...abs(diff) {
let value = min(x, y) + i
// Do something with value
}
Is there a better, or more elegant way to achieve this?
I guess the most explicit way of writing it would be:
for i in min(a, b)...max(a, b) {
// Do something with i
}
To exclude the first and last value, you can increment your lower limit and use the Swift ..< syntax:
let lowerLimit = min(a, b) + 1
let upperLimit = max(a, b)
for i in lowerLimit..<upperLimit {
// Do something with i
}

List comprehensions with float iterator in F#

Consider the following code:
let dl = 9.5 / 11.
let min = 21.5 + dl
let max = 40.5 - dl
let a = [ for z in min .. dl .. max -> z ] // should have 21 elements
let b = a.Length
"a" should have 21 elements but has got only 20 elements. The "max - dl" value is missing. I understand that float numbers are not precise, but I hoped that F# could work with that. If not then why F# supports List comprehensions with float iterator? To me, it is a source of bugs.
Online trial: http://tryfs.net/snippets/snippet-3H
Converting to decimals and looking at the numbers, it seems the 21st item would 'overshoot' max:
let dl = 9.5m / 11.m
let min = 21.5m + dl
let max = 40.5m - dl
let a = [ for z in min .. dl .. max -> z ] // should have 21 elements
let b = a.Length
let lastelement = List.nth a 19
let onemore = lastelement + dl
let overshoot = onemore - max
That is probably due to lack of precision in let dl = 9.5m / 11.m?
To get rid of this compounding error, you'll have to use another number system, i.e. Rational. F# Powerpack comes with a BigRational class that can be used like so:
let dl = 95N / 110N
let min = 215N / 10N + dl
let max = 405N / 10N - dl
let a = [ for z in min .. dl .. max -> z ] // Has 21 elements
let b = a.Length
Properly handling float precision issues can be tricky. You should not rely on float equality (that's what list comprehension implicitely does for the last element). List comprehensions on float are useful when you generate an infinite stream. In other cases, you should pay attention to the last comparison.
If you want a fixed number of elements, and include both lower and upper endpoints, I suggest you write this kind of function:
let range from to_ count =
assert (count > 1)
let count = count - 1
[ for i = 0 to count do yield from + float i * (to_ - from) / float count]
range 21.5 40.5 21
When I know the last element should be included, I sometimes do:
let a = [ for z in min .. dl .. max + dl*0.5 -> z ]
I suspect the problem is with the precision of floating point values. F# adds dl to the current value each time and checks if current <= max. Because of precision problems, it might jump over max and then check if max+ε <= max (which will yield false). And so the result will have only 20 items, and not 21.
After running your code, if you do:
> compare a.[19] max;;
val it : int = -1
It means max is greater than a.[19]
If we do calculations the same way the range operator does but grouping in two different ways and then compare them:
> compare (21.5+dl+dl+dl+dl+dl+dl+dl+dl) ((21.5+dl)+(dl+dl+dl+dl+dl+dl+dl));;
val it : int = 0
> compare (21.5+dl+dl+dl+dl+dl+dl+dl+dl+dl) ((21.5+dl)+(dl+dl+dl+dl+dl+dl+dl+dl));;
val it : int = -1
In this sample you can see how adding 7 times the same value in different order results in exactly the same value but if we try it 8 times the result changes depending on the grouping.
You're doing it 20 times.
So if you use the range operator with floats you should be aware of the precision problem.
But the same applies to any other calculation with floats.

Using F# Indexed Properties in a Type

I'm trying to convert the following C# into F#:
public class Matrix
{
double[,] matrix;
public int Cols
{
get
{
return this.matrix.GetUpperBound(1) + 1;
}
}
public int Rows
{
get
{
return this.matrix.GetUpperBound(0) + 1;
}
}
public Matrix(double[,] sourceMatrix)
{
this.matrix = new double[sourceMatrix.GetUpperBound(0) + 1, sourceMatrix.GetUpperBound(1) + 1];
for (int r = 0; r < this.Rows; r++)
{
for (int c = 0; c < this.Cols; c++)
{
this[r, c] = sourceMatrix[r, c];
}
}
}
public double this[int row, int col]
{
get
{
return this.matrix[row, col];
}
set
{
this.matrix[row, col] = value;
}
}
}
This is what I have so far:
type Matrix(sourceMatrix:double[,]) =
let mutable (matrix:double[,]) = Array2D.create (sourceMatrix.GetUpperBound(0) + 1) (sourceMatrix.GetUpperBound(1) + 1) 0.0
member this.Item
with get(x, y) = matrix.[(x, y)]
and set(x, y) value = matrix.[(x, y)] <- value
do
for i = 0 to matrix.[i].Length - 1 do
for j = (i + 1) to matrix.[j].Length - 1 do
this.[i].[j] = matrix.[i].[j]
My type above seems to have two problems I'm not sure how to resolve. The first one is that matrix.[(x, y)] is expected to have type `a[] but has type double[,]. The second is type definitions must have let/do bindings preceding member and interface definitions. The problem with that is I'm trying to populate an indexed property in the do block, which means I have to create it first.
Thanks in advance,
Bob
Regarding your first problem, you want to use matrix.[x,y] instead of matrix.[(x,y)] - your matrix is indexed by two integers, not by a tuple of integers (although these are conceptually similar).
Here's something roughly equivalent to your C#:
type Matrix(sourceMatrix:double[,]) =
let rows = sourceMatrix.GetUpperBound(0) + 1
let cols = sourceMatrix.GetUpperBound(1) + 1
let matrix = Array2D.zeroCreate<double> rows cols
do
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
matrix.[i,j] <- sourceMatrix.[i,j]
member this.Rows = rows
member this.Cols = cols
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value = matrix.[x, y] <- value
This assumes that your matrix can't actually be reassigned (e.g. in the C# you've posted, you could have made your matrix field readonly - unless there's additional code that you've hidden). Therefore, the number of rows and columns can be calculated once in the constructor since the entries of the matrix may change but its size won't.
However, if you want a more literal translation of your code, you can give your newly constructed instance a name (this in this case):
type Matrix(sourceMatrix:double[,]) as this =
let mutable matrix = Array2D.zeroCreate<double> (sourceMatrix.GetUpperBound(0) + 1) (sourceMatrix.GetUpperBound(1) + 1)
do
for i in 0 .. this.Rows - 1 do
for j in 0 .. this.Cols - 1 do
this.[i,j] <- sourceMatrix.[i,j]
member this.Rows = matrix.GetUpperBound(0) + 1
member this.Cols = matrix.GetUpperBound(1) + 1
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value = matrix.[x, y] <- value
type Matrix(sourceMatrix:double[,]) =
let matrix = Array2D.copy sourceMatrix
member this.Item
with get(x, y) = matrix.[x, y]
and set(x, y) value = matrix.[x, y] <- value

Adding Overloaded Constructor That Requires Initialization Code to Implicit F# Type

I currently have the following code:
type Matrix(sourceMatrix:double[,]) =
let rows = sourceMatrix.GetUpperBound(0) + 1
let cols = sourceMatrix.GetUpperBound(1) + 1
let matrix = Array2D.zeroCreate<double> rows cols
do
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
matrix.[i,j] <- sourceMatrix.[i,j]
new (rows, cols) = Matrix( Array2D.zeroCreate<double> rows cols)
new (boolSourceMatrix:bool[,]) = Matrix(Array2D.zeroCreate<double> rows cols)
for i in 0 .. rows - 1 do
for j in 0 .. cols - 1 do
if(boolSourceMatrix.[i,j]) then matrix.[i,j] <- 1.0
else matrix.[i,j] <- -1.0
My problem lies in the last constructor that takes a bool[,] parameter. The compiler isn't letting me get away with the two for loops I'm trying to use for initialization in this constructor. How can I make this work?
The easiest solution would be to just do this instead:
new (boolSourceMatrix) = Matrix(Array2D.map (fun b -> if b then 1.0 else -1.0) boolSourceMatrix)
The specific issue that you were running into is that the let-bound fields from the primary constructor aren't available in alternate constructors. To work around this, you could use an explicitly defined field, if you wanted. However, in this case it's better to take advantage of the additional functionality in the Array2D module.

Resources