Merge: Improve Comparator type-kindness
The Comparator class in Nit was a PITA because, with the traditional modelization with a generic class, Comparator is contravariant but Nit only allows covariance in its genericity.
Example:
~~~nit
var ao = new Array[Object].with_items(2,1,10)
ao.sort_with(alpha_comparator)
print ao.join(" ") # => 1 10 2
var ai = new Array[Int].with_items(2,1,10)
ai.sort_with(alpha_comparator)
# Static error: expected a Comparator[Int], got a Comparator[Object]
~~~
This PR implements the nice proposition of Etienne Gagnon to makes Comparator a non-generic class but use virtual types to control the type of compared elements.
It is clearly an improvement over the previous implementation:
* more expressive (++++)
* less code (+)
* simpler for the client (less generic stuff) (+)
* coherent with the `Comparable` hierarchy that also use virtual types (+)
* a little more complex for the lib (virtual type redefinition) (-)
* loss of information when things are typed with the interface `Comparator`, yielding to more potential covariance error at runtime (--)
While less type-safe than a full (and complex) contravariance solution, the proposed solution is still better in term of type-safety than dynamic languages and non-generic-non-virtual-type solutions (eg. Java4):
* runtime errors are detected earlier than with erasure or with dynamic typing (fail fast)
* some errors are still detected statically:
~~~
var a = [1,10,2,3]
alpha_comparator.sort(a)
print a.join(" ") #=> 1 10 2 3
default_comparator.sort(a)
print a.join(" ") #=> 1 2 3 10
var b = [true, false]
alpha_comparator.sort(b)
print b.join(" ") # => false true
default_comparator.sort(b)
# Static type error: expected Array[Comparable], got Array[Bool]
~~~
Original-Idea-By: Etienne M. Gagnon <egagnon@j-meg.com>
Pull-Request: #803
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>