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.
views:
187answers:
3Intuitively, a comparison operator like >
should always yield a boolean value!
You can answer the question a > b
with yes or no, but not with 3
or new Stopwatch()
.
When it could return anything else, something like
if a < b then
would make no sense any more.
F#-objects (tuples, lists etc) often implement IComparable
or IStructuralComparable
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.
greater :: (Ord a) => a -> a -> Bool
greater a b = a < b
Comparing uncomparable types would fail at compile-time.
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.