我想为我的类型(<,>,<=,> =等)创建自定义比较运算符。我尝试过:
type MyType() =
static member (>) (left: MyType, right: int) = true
let foo = new MyType();
let bar = foo > 12;
并收到错误:
The type 'MyType' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface
(为什么像运算符重载这样的语言功能依赖于来自框架的接口IComparable?该语言及其使用的框架不应该独立吗?)所以我尝试:
type MyType() =
interface IComparable
member self.CompareTo yobj = true
interface IComparable<int>
member self.CompareTo yobj = true
static member (>) (left: MyType, right: int) = true
我得到:
This expression was expected to have type 'MyType' but here has type 'int'
如何获得预期的行为?
答案 0 :(得分:3)
我不知道为什么F#
不允许我写类似C#
这样的代码。
public class MyType
{
public int Value {get;set;}
public static bool operator >(MyType left, int right)
{
return left.Value > right;
}
public static bool operator <(MyType left, int right)
{
return left.Value < right;
}
}
即使该类型未实现IComparable
接口,我也可以将其与int
进行如下比较:
t > 2
t < 6
似乎F#
将(>)
视为T' -> T' -> bool
:
val ( > ):
x: 'T (requires comparison )->
y: 'T (requires comparison )
-> bool
这表明:
T'
需要进行比较(IComparable
)如果我对它的理解正确,这就是为什么出现以下错误的原因:
该表达式的类型应为'MyType',但此处的类型应为'int'
即使您已经实现了IComparable
接口,标准(>)
仍要求left和right参数属于同一类型。
一种解决方法是创建一个自定义函数 (>)
,该函数直接接受左侧的MyType
和右侧的int
参数:
type MyType(info) = member x.Info : int = infolet inline (>) (left: MyType) (right: int) = left.Info > right let inline (<) (left: MyType) (right: int) = left.Info < right// see https://stackoverflow.com/questions/19682432/global-operator-overloading-in-f let inline (>) (left) (right) = match (box left, box right) with | (:? MyType as l, :? int as r ) -> l.Info > int right | (:? IComparable as left', :? IComparable )-> let r = left'.CompareTo right r > 0 | _ -> failwith "not support type " let inline (<) (left) (right) = match (box left, box right) with | (:? MyType as l, :? int as r ) -> l.Info < int right | (:? IComparable as left', :? IComparable )-> let r = left'.CompareTo right r < 0 | _ -> failwith "not support type "
答案 1 :(得分:1)
请注意,>
的声明中还会发出警告:
名称“(>)”不应用作成员名称。要定义类型的比较语义,请实现“ System.IComparable”接口。如果要定义静态成员以供其他CLI语言使用,请改用名称“ op_GreaterThan”。
正如它的答案所显示的,这是因为>
是在满足'T
约束的两个comparable
上定义的。
F#中没有像C#中那样的运算符重载。这是因为运算符是函数,并且函数不能重载。
因此,您的选择是(a)根据警告的建议实施System.IComparable
,或(b)根据建议使用inline
函数的变通办法。