matrix - 如何在实现中缀运算符时避免循环依赖

标签 matrix vector f# operators static-methods

假设我希望在 F# 中实现一个 Vector 和一个 Matrix 类。该语言不允许循环依赖,所以我不能同时让 Vector 类引用 Matrix 类,反之亦然。让我们进一步说,我做出的选择是两个类都不应该依赖于另一个类(与例如 Vector 依赖于 Matrix 而不是相反的情况相反)。

现在我想实现 Matrix 实例与 Vector 实例的右乘,即 a * b,其中 a 是 Matrix,b 是 Vector。首先想到的是将 op_Multiply 声明为 Matrix 类中的静态成员方法。在 C# 中,这意味着有一个带有这样签名的静态方法

public static Vector operator *(Matrix matrix, Vector vector);

例如矩阵类。但是,此操作同时依赖于 Vector 类和 Matrix 类,因此不能在 Matrix 类和 Vector 类中声明,因为它们不允许相互依赖。

下一个想法可能是将其声明为某种扩展方法,在 F# 中具有以下效果:

[<Extension>]
static member (*) (matrix : IMatrix, vector : IVector) =
    ...

然而,这只允许我写类似的东西

a.op_Multiply(b)

不是

a * b

从某种意义上说,这里的问题是我不会编写“运算符扩展方法”。如何定义乘法方法,避免 Matrix 和 Vector 相互依赖,同时又能写出类似“a * b”的内容?

最佳答案

我认为您可以将运算符写成 let具有 [<AutoOpen>] 的模块中的绑定(bind)函数属性:

module Foo =
    type Bar = Bar of string

module Ploeh =
    type Fnaah = Fnaah of string

[<AutoOpen>]
module Operators =
    let (+) (Foo.Bar b) (Ploeh.Fnaah f) = b + f

open Foo
open Ploeh

let sum = (Bar "sgryt") + (Fnaah "ler")

这至少会在 FSI 中产生预期的输出:

> let sum = (Bar "sgryt") + (Fnaah "ler");;    
val sum : string = "sgrytler"

这不是我经常做的事情,所以我不能说是否有一些极端情况会使这项工作在实践中不太理想......

关于matrix - 如何在实现中缀运算符时避免循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40790478/

相关文章:

arrays - 将每个条目随机替换为其四个邻居之一

Python - Pandas 数据框中日期的日历 View

c++ - 指针 vector 上的 std::find()

algorithm - 获取列表列表的类笛卡尔积,长度不等,函数 ('a -> ' b list) 应用于每个项目

javascript - 将 SVG 重置为原始变换矩阵

c 初学者, vector

r - 根据条件拆分为 list(),省略 False 元素

f# - 嵌套类型提供者

f# - 如何创建扩展方法 (F#)?

Python - 嵌套 for 循环中两个不同矩阵的错误结果