问题
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
回答1:
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
回答2:
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
来源:https://stackoverflow.com/questions/5206911/using-f-indexed-properties-in-a-type