F# 和 op_GreaterThan
我最近尝试利用 Microsoft Solver Foundation Services 在 F# 中编写一些内容,在这样做时我遇到了一个问题:我必须表达一个 (Term > Term) 条件,在 C# 中可以简单地表示为 t1 > Term。 t2 并返回另一个 Term 对象。 相反,在 F# 中,我必须调用 Term.op_GreaterThan 才能获得与使用 t1 > 相同的结果。 t2 将产生一个布尔值而不是一个术语。
现在我想知道为什么 F# 仅在产生布尔值时才选择 op_GreaterThan? F# 对 t1 > 的解释是什么意思? t2 有,而 Term 没有实现 IComparable?
请注意,我理解为什么要基于结构比较概念进行相等和整体相等的操作,我只是不明白如何将其扩展到“大于”/“小于”比较。
I've recently tried to write something in F# making use of Microsoft Solver Foundation Services and while doing so I bumped into an issue: I had to express a (Term > Term) condition which in C# could simply be expressed as t1 > t2 and returns another Term object. In F#, instead, I had to call Term.op_GreaterThan in order to achieve the same result as using t1 > t2 would yield a bool and not a term.
Now I'm wondering why is F# only picking op_GreaterThan if it yields a boolean?
And what meaning would F#'s interpretation of t1 > t2 have while Term doesn't implement IComparable?
Please mind that I understand why doing such a thing with equality and the whole equality based on structural comparison notion, I just don't get how that could be extended to "greater than"/"smaller than" comparisons.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
教科书答案:
运算符重载不是公共语言规范的一部分,这意味着编译器编写者可以根据需要随意忽略或仅部分支持它。 作为库编写者,您有责任为人们提供与班级一起工作的替代方法。
务实的回答:
因为这从一开始就是一件愚蠢的事情。 显式创建 op_GreaterThan 方法来进行比较。 也就是说,你不应该用它做“有趣”的事情,比如连接两个术语。 CLR 只允许您滥用它,因为它需要支持 C++ 等遗留语言。
顺便说一句,有一个专门用于将两个事物连接在一起的重载。 它称为 op_Concatenate。 您确实应该考虑使用它而不是 op_GreaterThan。
编辑
几乎很好的答案:
在 F# 中,我提到的连接运算符是 ^。
我称这为几乎好的答案,因为我不太确定 C# 是否支持它。 我认为它只允许在 VB 和 F# 中使用。
编辑 #2
看来 F# 根本不支持 ^ 重载。
编辑 #3
这是怎么回事? F# 不尊重 > 根本没有操作员。 当然,您可以重载它,并且它会正确发出 op_GreaterThan 方法,但它会忽略它。 它甚至不尝试使用 op_GreaterThan,而是查找 System.IComparable 接口。
更糟糕的是,这是运行时检查。 尽管它可以静态地确定类 Foo 没有实现 IComparable,但它仍然会继续编译代码。
Textbook Answer:
Operator overloading is not part of the Common Language Specification, meaning compiler writers are free to ignore or only partially support it if they feel like. As a library writer, you are responsible for providing alternate means for people to work with the class.
Pragmatic Answer:
Because it is a stupid thing to do in the first place. The op_GreaterThan method was explicitly created to make comparisons. That it, you aren't supposed to do 'interesting' things with it like concatinating two terms. The CLR only lets you abuse it because it needs to support legacy languages like C++.
By the way, there is an overload specifically for joining two things together. It is called op_Concatenate. You really should consider using it instead of op_GreaterThan.
EDIT
Almost Good Answer:
In F# the concatination operator I mentioned is ^.
I call this the almost-good answer because I'm not so sure that C# supports it. I think it is only allowed in VB and F#.
EDIT #2
It seems F# isn't honoring the ^ overload after all.
EDIT #3
WTF is going on here? F# doesn't honor the > operator at all. Sure you can overload it, and it will emit the op_GreaterThan method correctly, but it ignores it. It doesn't even try to use op_GreaterThan, instead it looks for the System.IComparable interface.
Even worse, this is a runtime check. Even though it can statically determine that class Foo doesn't implement IComparable, it still goes ahead and compiles the code anyways.
直观上,像
>
这样的比较运算符应该总是产生一个布尔值!您可以回答问题
a > b
为 yes 或 no,但不为3
或new Stopwatch()
。当它可以返回任何其他东西时,类似的东西
就不再有意义了。
F# 对象(元组、列表等)通常实现 IComparable 或 IStructuralComparable ,例如可以按字典顺序对元组进行排序。
*注意:
恕我直言,允许比较任何对象然后在运行时抛出异常并不是最好的解决方案。 Haskell 使用类型类更好地解决了这个问题。
比较不可比较的类型将在编译时失败。
Intuitively, a comparison operator like
>
should always yield a boolean value!You can answer the question
a > b
with yes or no, but not with3
ornew Stopwatch()
.When it could return anything else, something like
would make no sense any more.
F#-objects (tuples, lists etc) often implement
IComparable
orIStructuralComparable
which can for example sort a tuple lexicographically.*Note:
IMHO, it's not the best solution to be allowed to compare any objects and then throw exceptions at runtime. Haskell has solved this better using typeclasses.
Comparing uncomparable types would fail at compile-time.
您不必使用 < 和> 运营商。 Solver Foundation Services Model 类具有 Greater 和 Less 方法,您应该能够使用它们。
You don't have to use the < and > operators. The Solver Foundation Services Model class has Greater and Less methods, you should be able to use those instead.