3

好的,有人可以向我解释为什么 F# 允许您重载 > 和 ^ 运算符,但不允许您使用它们吗?

+ (op_Addition): Works just fine.
^ (op_Concatenate): Compiler error in F#. Apparently only strings can be concatenated.
> (op_GreaterThan): Runtime Error – Failure during generic comparison: the type Program+OppTest4 does not implement the System.IComparable interface.

如果我将我的 F# 代码编译为库并使用 VB 中的这些运算符,它们都可以工作。如果我使用 C# 中的这些运算符,除了 op_Concatenate 之外的所有运算符都可以工作(如预期的那样)。但是 F# 不仅忽略了其中的一些,静态类型检查器甚至都懒得告诉你它打算这样做。

编辑代码示例

type OppTest4(value: int) =
   member this.value = value
   static member (^) (left : OppTest4, right : OppTest4) =
     OppTest4( Int32.Parse( left.value.ToString() ^ right.value.ToString()  ))
   static member (+) (left : OppTest4, right : OppTest4) =
     OppTest4(left.value + right.value )
   static member (>) (left : OppTest4, right : OppTest4) =
     left.value > right.value
   static member (<) (left : OppTest4, right : OppTest4) =
     left.value < right.value
4

2 回答 2

4

F# 对这些运算符符号具有默认含义,这对 F# 来说是合理的。您始终可以定义自己的含义来掩盖默认值,例如

let (>) x y = ...

例如,您可以将此运算符定义为表示“T.operator>(U)”(假设 x 的类型为 T,y 的类型为 U)。

有关默认定义,请参阅源分发中 FSharp.Core 中的 prim-types.fs。(它们很重要!)

鉴于 (1) 缺乏对 CLR 上的类型类机制的支持(用于在一组其他不相关的类型之间定义公共语义)和 (2) 原始类型(如“int”)经常需要对任何编程语言实现进行特殊处理(例如 System.Int32 没有定义 operator+ 方法,但大多数编程语言选择表现得好像存在这样的方法),很难想象任何通用的跨所有语言的可互操作的操作符的东西今天在.Net 上。有很多设计权衡取决于语言选择做什么(太多的交互问题在这里总结)。在任何情况下,您都应该能够从 F# 调用任何方法,并且如果不希望使用默认的运算符行为,您可以将运算符重新定义(阴影)为您想要的行为。

编辑

我在

http://cs.hubfs.net/forums/thread/10869.aspx

于 2009-06-08T23:53:59.553 回答
0

我同意,存在不一致:可以定义运算符,但不能使用。

你在问,为什么 F# 设计者决定实现与 System.IComparable 接口的比较而不是运算符重载?我不知道为什么,但是在 OO 语言中,我更喜欢 IComparable 而不是运算符重载。因此,我建议 F# 开发人员打破 C# 兼容性并禁止“静态成员 (>) (...)”语法糖。

如果您要问如何调用这些重载运算符,这很容易:使用 op_Concatenate、op_GreaterThan 或 op_LessThan 静态成员。(真的,我有一个编译器警告,描述了这个问题。F# 1.9.6.16)

没有任何编译器警告的运行时错误转换为 System.IComparable 绝对是一个错误。您可以将其发送至 fsbugs@microsoft.com。

于 2009-06-09T15:56:40.813 回答