【问题标题】:How to use overloaded static operators如何使用重载的静态运算符
【发布时间】:2016-11-29 11:31:45
【问题描述】:

我正在用 F# 编写一个小型矩阵库(主要是包装器方法),并且在静态运算符方法的重载方面存在问题,F# 选择了一个我不打算这样做的重载。

我有一个模块,我在其中定义了矩阵与向量的右乘:

[<AutoOpen>]
module MatrixOps =

let (*) (matrix : IMatrix) (vector : IVector) =
    (...)

这让我可以写一些东西,例如A * v 其中 A 是 IMatrix,v 是 IVector。但是,我现在在上面的 let-binding 下添加以下行:

let z = 1.0 * 2.0

然后,F# 编译器将此识别为错误。悬停在“1.0”上,我得到:“'float' 类型与'IMatrix' 类型不兼容,同样,悬停在“2.0”上,我得到:“'float' 类型与类型'不兼容' IVector'”。这里发生的情况似乎是 F# 编译器未能将乘法运算符应用于浮点数,而是将运算符应用于 IMatrix 和 IVector。如果我改为写

let z = (1.0 : float) * (2.0 : float)

问题仍然存在,因此添加显式类型注释无济于事。如何确保 F# 选择浮动乘法运算符而不是我上面定义的 IMatrix / IVector 运算符?

【问题讨论】:

  • 你想让重载成为其中一个对象类型的静态成员,然后它会像你想要的那样工作
  • 好的。但是还有其他方法吗?如果乘法方法在 IMatrix 或 IVector 接口上,那么我将引入一个不需要的依赖项。
  • 这不是依赖。无论如何你都需要这些类型
  • 好吧,如果我将静态方法 IMatrix * IVector -> IVector 放在例如IMatrix 接口,则 IMatrix 依赖于 IVector。是的,无论如何我都需要这些类型,但我不需要这些类型相互依赖。现在,IMatrix 或 IVector 都不依赖于另一个,我更喜欢这样。
  • @AlexanderSokol 请参阅我的答案下方的注释。如果按照我建议的方式设计重载,另一个优势是它们不会相互依赖。

标签: f# operator-overloading static-methods type-inference


【解决方案1】:

F# 不允许您仅通过添加 let 绑定函数来定义重载。

F# 支持标准 .NET 实例或静态成员重载,因此在这种情况下您需要添加静态成员:

type Matrix =
  static member (*) (matrix : Matrix) (vector : IVector) = ..

注意:我建议您不要使用矩阵和向量之间的重载设计。如果你继续以这种方式定义重载,我的意思是在混合类型之间,重载决议可能会变得模棱两可。

最好只在矩阵之间定义重载,然后在向量之间定义另一个集合。然后你可以定义一个像asMatrix 这样的函数,它允许你将一个向量包装在一个矩阵中,然后将矩阵相乘。

【讨论】:

  • 我认为这是一个错字:最好定义矩阵和向量之间的重载
  • @FyodorSoikin 之类的,既然你提到了,我注意到它并不清楚。我会改写它。谢谢!
  • 谢谢。我认为您对 asMatrix 的评论是合理的。我确实有一些后续问题。如果我(字面上)执行上述操作,Matrix 将依赖于 IVector。我宁愿不把两者结合起来。避免耦合的一种潜在方法是定义“IMatrix 接口上的静态扩展方法”,但接口不能有静态方法。也许实现这项工作的唯一方法是引入依赖项?
  • @AlexanderSokol 当你说'如果我真的做到了上述'你是什么意思?我的代码示例还是我的建议?
  • 哦,我的意思是代码,也就是说,如果我真的把静态成员放在 Matrix 类中。
猜你喜欢
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
相关资源
最近更新 更多