【问题标题】:Using F# Indexed Properties in a Type在类型中使用 F# 索引属性
【发布时间】:2012-07-26 06:30:50
【问题描述】:

我正在尝试将以下 C# 转换为 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;
         }
       }
     }

这是我目前所拥有的:

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]

我上面的类型似乎有两个问题,我不知道如何解决。第一个是矩阵。[(x, y)] 应该具有类型 `a[] 但具有类型 double[,]。第二个是类型定义必须在成员和接口定义之前有 let/do 绑定。问题是我试图在 do 块中填充索引属性,这意味着我必须先创建它。

提前致谢,

鲍勃

【问题讨论】:

    标签: f# types indexed-properties


    【解决方案1】:

    关于您的第一个问题,您想使用 matrix.[x,y] 而不是 matrix.[(x,y)] - 您的矩阵由两个整数索引,而不是由整数元组索引(尽管它们在概念上相似)。

    这里的东西大致相当于你的 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
    

    这假设您的矩阵实际上无法重新分配(例如,在您发布的 C# 中,您可以将 matrix 字段设为 readonly - 除非您隐藏了其他代码)。因此,行数和列数可以在构造函数中计算一次,因为矩阵的条目可能会改变,但它的大小不会改变。

    但是,如果您想要更直接地翻译您的代码,您可以为新构建的实例命名(在这种情况下为this):

    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
    

    【讨论】:

    • 优秀的答案,并且很好地抓住了只读,这是您的正确假设。最初的 C# 不是我的,我忽略了这一点。必须很好地同时擅长 C# 和 F#。 :)
    • 如果有人感兴趣,我在这个问题上添加了一个后续问题:stackoverflow.com/questions/5212570/…
    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 2016-07-15
      • 1970-01-01
      • 2023-04-08
      相关资源
      最近更新 更多