4

我最近尝试使用 Microsoft Solver Foundation Services 在 F# 中编写一些东西,在这样做的同时我遇到了一个问题:我必须表达一个 (Term > Term) 条件,在 C# 中可以简单地表示为 t1 > t2 和返回另一个 Term 对象。相反,在 F# 中,我必须调用 Term.op_GreaterThan 才能获得与使用 t1 > t2 会产生布尔值而不是术语相同的结果。
现在我想知道为什么 F# 只选择 op_GreaterThan 如果它产生一个布尔值?当 Term 没有实现 IComparable 时,F# 对 t1 > t2 的解释有什么意义?
请注意,我理解为什么基于结构比较概念在平等和整体平等的情况下做这样的事情,我只是不明白如何将其扩展到“大于”/

4

3 回答 3

4

教科书答案:

运算符重载不是公共语言规范的一部分,这意味着编译器编写者可以随意忽略或仅部分支持它,如果他们愿意的话。作为图书馆作者,您有责任为人们提供与班级合作的替代方式。

务实的回答:

因为一开始做这件事就是一件愚蠢的事。显式创建了 op_GreaterThan 方法以进行比较。也就是说,你不应该用它做“有趣”的事情,比如连接两个术语。CLR 只允许你滥用它,因为它需要支持像 C++ 这样的遗留语言。

顺便说一句,有一个重载专门用于将两个东西连接在一起。它被称为 op_Concatenate。你真的应该考虑使用它而不是 op_GreaterThan。

编辑

几乎是好的答案:

在 F# 中,我提到的连接运算符是 ^。

我称这为几乎不错的答案,因为我不太确定 C# 是否支持它。我认为它只允许在 VB 和 F# 中使用。

编辑#2

看来 F# 毕竟不尊重 ^ 重载。

编辑#3

WTF在这里进行吗?F# 根本不尊重 > 运算符。当然你可以重载它,它会正确地发出 op_GreaterThan 方法,但它会忽略它。它甚至不尝试使用 op_GreaterThan,而是寻找 System.IComparable 接口。

更糟糕的是,这是一个运行时检查。即使它可以静态确定类 Foo 没有实现 IComparable,它仍然会继续编译代码。

于 2009-06-08T20:55:37.790 回答
2

直观地说,比较运算符 like>应该总是产生一个布尔值!

a > b您可以用是或否来回答这个问题,但不能用3or来回答new Stopwatch()

当它可以返回其他任何东西时,例如

if a < b then

将不再有意义。

F# 对象(元组、列表等)经常实现IComparableIStructuralComparable例如可以按字典顺序对元组进行排序。

*笔记:

恕我直言,允许比较任何对象然后在运行时抛出异常并不是最好的解决方案。Haskell 使用类型类更好地解决了这个问题。

greater :: (Ord a) => a -> a -> Bool
greater a b = a < b

比较不可比较的类型会在编译时失败。

于 2009-06-08T18:02:48.830 回答
0

您不必使用 < 和 > 运算符。Solver Foundation Services Model 类具有 Greater 和 Less 方法,您应该可以使用它们。

于 2009-06-10T04:33:37.723 回答