如何在不覆盖现有运算符的情况下定义运算符重载

时间:2018-06-11 04:32:58

标签: f#

如何在不覆盖现有定义的情况下重载基本运算符(+, - ,*)?阅读关于这个主题的其他一些主题,我无法理解该怎么做。具体来说,我希望直接在Array2D类型上定义矩阵运算。 MathNet.Numerics以某种方式设法为其Matrix和Vector类型做到这一点但不确定如何。定义常规函数而不是使用运算符完全满足线性代数繁重应用中的逻辑。

type Array() =
    static member (+) (A : float[,], B : float[,]) =
        let r = A.GetLength 0
        let c = A.GetLength 1
        let C = Array2D.create r c 0.
        for i in 0..r-1 do
            for j in 0..c-1 do
                C.[i, j] <- A.[i, j] + B.[i, j]
        C


let a1 = Array2D.create 4 4 1.
let a2 = Array2D.create 4 4 1.
let a3 = a1 + a2   // type float[,] does not support the operator '+'
let y = 2 + 3      // don't want this overridden by something like a 'let inline...'

1 个答案:

答案 0 :(得分:5)

MathNet.Numerics如果为自己的类型提供运算符,作为其定义的一部分,不应该有很多问题。

您尝试做的是使用扩展方法为操作员提供 - 我不认为目前可能。

最简单的方法是提供稍微不同的运算符,让我们说+.,这样就不会发生冲突,但代码仍然很容易理解。这就是OCaml为区分int和float运算符所做的事情(而F#为自定义运算符选择符号提供了很大的空间)。

let inline (+.) (A: float[,]) (B: float[,]) = 
    ...

let a3 = a1 +. a2 

还有其他解决方案 - 您可以使用单个案例联合来包装2D数组并将运算符定义为该类型的成员,或者您可以使用SRTP将运算符修补到现有类型并使其内联在编译时,但这样做也会以某种方式模糊逻辑。