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...'
解决方案
如果作为定义的一部分,MathNet.Numerics 为自己的类型提供运算符,那么这样做应该不会有太大问题。
您要做的是使用扩展方法提供运算符-我认为目前不可能。
最简单的方法是提供一个稍微不同的运算符,比如说+.
,这样就不会发生冲突,但代码仍然很容易理解。例如,这就是 OCaml 用来区分 int 和 float 运算符的方法(而 F# 为您提供了为自定义运算符挑选符号的很大空间)。
let inline (+.) (A: float[,]) (B: float[,]) =
...
let a3 = a1 +. a2
还有其他解决方案 - 您可以使用单个案例联合来包装 2D 数组并将运算符定义为该类型的成员,或者您可以使用 SRTP 将运算符修补到现有类型并在编译时将其内联,但那样做也会以一种或另一种方式模糊逻辑。
推荐阅读
- python-3.x - 查找并单击没有名称、ID 或类别的选择?
- html - 如果没有设置 flex-basis 或 width ,flexbox 如何计算 flex-item 的宽度?
- c# - 如何将对象传递给c#模型的变量
- reactjs - TypeError : this.refs.function 不是函数
- swift - 默认情况下,TabBar 上的选定项目未突出显示
- python - 如何使用 tkinter 在 Python 中修复“ValueError:无法将字符串转换为浮点数:”
- ruby-on-rails - 通过关联向has_many中的连接表添加一个额外的字段
- gradle - 如何定义 CodeNarc Gradle 插件将扫描/分析的文件夹/目录
- selenium - 如何在 Protractor 项目中设置 chromeDriver 位置
- python - 使用scrapy从xpath响应中获取列表的每一行的布尔值