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

现在我想用 Vector 实例实现 Matrix 实例的右乘,即 a * b 其中 a 是一个矩阵,b 是一个向量。第一个想法是将 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/

10-16 05:16