首页 > 解决方案 > 如何在不覆盖现有运算符的情况下定义运算符重载

问题描述

如何在不覆盖现有定义的情况下重载 (+, -, *) 等基本运算符?阅读有关此主题的其他一些主题时,我不知道该怎么做。具体来说,我希望直接在 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...'

标签: f#

解决方案


如果作为定义的一部分,MathNet.Numerics 为自己的类型提供运算符,那么这样做应该不会有太大问题。

您要做的是使用扩展方法提供运算符-我认为目前不可能。

最简单的方法是提供一个稍微不同的运算符,比如说+.,这样就不会发生冲突,但代码仍然很容易理解。例如,这就是 OCaml 用来区分 int 和 float 运算符的方法(而 F# 为您提供了为自定义运算符挑选符号的很大空间)。

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

let a3 = a1 +. a2 

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


推荐阅读