Here is the C# code I am trying to translate:
public bool equals(Matrix matrix, int precision)
{
if (precision < 0)
{
throw new MatrixError("Precision can't be a negative number.");
}
double test = Math.Pow(10.0, precision);
if (double.IsInfinity(test) || (test > long.MaxValue))
{
throw new MatrixError("Precision of " + precision
+ " decimal places is not supported.");
}
precision = (int)Math.Pow(10, precision);
for (int r = 0; r < this.Rows; r++)
{
for (int c = 0; c < this.Cols; c++)
{
if ((long)(this[r, c] * precision) != (long)(matrix[r, c] * precision))
{
return false;
}
}
}
return true;
}
Here is what I have so far:
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]
///The number of Rows in this Matrix.
member this.Rows = rows
///The number of Columns in this Matrix.
member this.Cols = cols
member this.Equals(matrix:Matrix, precision:int) =
if(precision < 0) then raise (new ArgumentOutOfRangeException("Precision can't be a negative number."))
let (test:double) = Math.Pow(10.0, double(precision))
if(System.Double.IsInfinity(test) || (test > double(System.Int32.MaxValue))) then raise (new ArgumentOutOfRangeException("Precision of " + precision.ToString() + " decimal places is not supported."))
let precision = int(Math.Pow(10.0, double(precision)))
As you can see what I have written so far is loaded with type casts which probably means my code is not written the way it should be. The unfinished part needs the method to return on the first element which returns false when evaluated to a certain precision. I’m sure there must be some elegant F# code to achieve this and clearly I am nowhere near it. I was trying to figure out if the Array2D class had some method on it that would allow me to do this, but I wasn’t able to find it if there is. I am aware of the PowerPack Matrix class and will use it eventually, but for now I’m trying to learn F# by translating C# code I understand into F#. Easier said than done apparently. 🙂 I believe I’ve added all the relevant F# code in the type I’m creating. Let me know if I’m missing something.
An elegant and high-level way to write this that probably won’t be extremely efficient is to use lazy sequence expressions:
The idea is that the sequence will generate
falseas soon as the first element in the matrix matches the condition. Then theSeq.forallfunction immediately returnsfalse(and stops iterating over the sequence).In practice, you’ll probably need to implement this using recursive function to make it efficient. This is not particularly nice (because breaking out of loops cannot be done in F#), but you shouldn’t need code like this too often: