【问题标题】:F# overloading operators for generic types泛型类型的 F# 重载运算符
【发布时间】:2016-01-25 04:46:49
【问题描述】:

我正在尝试定义一个包含带有运算符重载的泛型类型的模块,但单声道编译器似乎忽略了我在实现文件中的类型。我的接口文件如下所示:

module Vector
[<Sealed>]
type Vector<'a> =
  static member ( +. ) : Vector<'a> * Vector<'a> -> Vector<'a>
val make : 'a * 'a -> Vector<'a>
val coord : Vector<'a> -> 'a * 'a

而我的实现是

module Vector
type Vector<'a> =
  | V of 'a * 'a
  static member ( +. ) (V(x1,y1), V(x2,y2)) = V(x1+x2, y1+y2)
let make (x, y) = V(x, y)
let coord (V(x, y)) = (x, y)

当我编译时,我得到:

fsharpc -a VectorParam.fsi VectorParam.fs
F# Compiler for F# 3.1 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License

/.../VectorParam.fs(4,19): error FS0034: Module 'Vector' contains
    static member Vector.( +. ) : Vector<int> * Vector<int> -> Vector<int>    
but its signature specifies
    static member Vector.( +. ) : Vector<'a> * Vector<'a> -> Vector<'a>    
The types differ

我不明白,因为我使用的是标记类型。而且,如果我删除所有“”并将剩余的类型别名替换为浮点数,那么一切正常。谁能帮我理解正确的语法?

谢谢,乔恩

【问题讨论】:

标签: generics f# mono operator-overloading inline


【解决方案1】:

我会从放弃 fsi 文件开始——这并不是真正需要的。如果您确实需要它,创建它的最简单方法是将文件粘贴到 fsi 并复制输出,或者您可以让编译器为您生成一个。

在对数值类型进行类型推断时,最好使用内联成员。原因是 F# 真的很喜欢使用 int - 并且一旦它看到没有进一步约束的+,编译器就会推断出int。这是因为在 .NET 类型系统中,并非 F# 使用的所有约束都可以表达。使用inline 可以绕过这一点。

这是一个可以直接粘贴到 fsi 中的简单示例:

type Vector<'a> =
  | V of 'a * 'a
  static member inline ( +. ) (V(x1,y1), V(x2,y2)) = V(x1+x2, y1+y2);;

V(1,1) +. V(1,1);;
V(1.,1.) +. V(1.,1.);;

【讨论】:

  • 快速的 Google 搜索显示了许多关于“静态解析类型参数”以及它们如何允许鸭子类型的页面。可以在以下位置找到一个很好的博客概述它:theburningmonk.com/2011/12/…
  • 感谢您提供静态类型的指针。我正在通过 mac 上的 mono 实现研究 fsharp 中的模块构建,我真的很喜欢指定接口的想法。将内联与 (+) 上的静态类型结合使用可以使模块构建时没有编译错误,但这给了我一个新的错误,当使用库时:“值 '(+.)' 被标记为内联,但它的实现使用了无法充分访问的内部或私人功能”。我认为这意味着内联和模块不会混合。所以我又卡住了。谢谢。
  • @JonSporring - 因为内联通过文本替换有效地工作,所以调用代码需要可以访问您使用的函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-28
  • 2018-10-19
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
相关资源
最近更新 更多