F#和运算符重载:(>)和(^)

时间:2009-06-08 23:21:26

标签: f# operator-overloading static-typing

好的,有人可以向我解释为什么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

2 个答案:

答案 0 :(得分:4)

F#具有对于F#合理的这些运算符符号的默认含义。您可以随时定义影响默认值的自己的含义,即la

let (>) x y = ...

例如,您可以将此运算符定义为“T.operator&gt;(U)”(假设x具有类型T且y具有类型U)。

请参阅源代码分发中FSharp.Core中的prim-types.fs以获取默认定义。 (它们非常重要!)

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

修改

我在

添加了更多细节

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

答案 1 :(得分:0)

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

您是否在问,为什么F#设计师决定与System.IComparable接口进行比较而不是运算符重载?我不知道为什么,但在OO语言中我更喜欢IComparable而不是运算符重载。所以,我建议F#开发人员打破C#兼容性并禁止“静态成员(&gt;)(...)”语法糖。

如果您正在询问如何调用这些重载运算符,则非常简单:使用op_Concatenate,op_GreaterThan或op_LessThan静态成员。 (真的,我有一个编译器警告,描述了这个问题.F#1.9.6.16)

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