eclipse-archived/ceylon

what to do about Comparable

Closed this issue · 11 comments

After #7395, I changed Comparable to be invariant.

@jvasileff points out that a bunch of our functions including sort() and max() don't work as well when you have things that indirectly implement comparable. It is possible to rescue all these functions by adding a new type parameter C and having parameters of type, for example, Element & Comparable<C> or {Element & Comparable<C>*}.

However, that's pretty messy and I don't see it as acceptable. There's two reasonable solutions:

  1. Make Comparable contravariant and remove its self type.

  2. Taking advantage of #7408, define Comparable as follows:

    shared interface Comparable<Other> of Other 
            given Other satisfies Comparable<in Other> { ... }
    

    Then functions like sort() and max() just use the same type constraint given Other satisfies Comparable<in Other>.

I like solution 2, assuming that #7408 doesn't run into some terrible snag.

Is option 2 still sound re coverage?

I believe so, yes, since T is not considered to cover Comparable<in T>.

I have pushed my proposed solution #2, so that people can try it out.

After sleeping on this, I think the cleanest solution is just to:

  1. Make Comparable contravariant and remove its self type.

So I've done that. Thanks to @jvasileff for pointing out the problems with making Comparable invariant.

Option 1 seems reasonable to me given that it makes things easy for developers (they don't have to remember the in annotation).

Although with 1, I don't see a justification for given Other satisfies Comparable<Other>. I mean, if we can have class C() satisfies Comparable<Integer>, how is it relevant to C's satisfaction that Integer is comparable to itself?

@jvasileff pfff, TBH I don't even remember. But I guess the idea is that a total order is a binary relation on a given set. It's not a binary relation between members of one set and members of a second distinct set.

What would it mean to say that a string is smaller than an integer?

What would it mean to say that a string is smaller than an integer?

Yeah, I think that sort of thing just creates problems. But the constraint doesn't prevent that.

dlkw commented

I think it's rather strange if you are allowed to write a <= b, but b>a gives a compile error. This is quite unexpected for a total order.

dlkw commented

It's been a long day. Should have written a < b vs. b > a.

@dlkw Yeah, types like that shouldn't be written. But I think the original question (option 1 vs. 2) is about whether it's important for the type system to prevent someone from creating such types, verse the convenience of having Comparable be contravariant.

Right.