I'm playing with the QuickSort example at the start of Scala By Example and trying to adapt it for a generic type A
, rather than just Int
s.
What I've got working so far is
def sort[A <: Ordered[A]](xs: Array[A])
Which allows sort
to run on all types that are reflexively ordered, like .RichBoolean
But what I'd also like to allow types A
where they extend Ordered[B]
where B is a superclass of A (so, for instance, anything that extends Ordered[Any]
).
How can I say this?
What I actually got to work, thanks to agilesteel's answer:
case class X( i : Int ) extends Ordered[X] {
def compare( x : X ) = x.i - i
}
class Y( i : Int, j : Int ) extends X(i)
case class Z( i : Int ) extends Ordered[Any] {
def compare( a : Any ) : Int = {
if (! a.isInstanceOf[Z] )
sys.error("whoops")
val z = a.asInstanceOf[Z]
z.i - i
}
}
object QuickSort {
def main( args : Array[String] ) {
val xs = Array( 3, 1, 2, 4 ) map X
sort( xs );
val ys = Array( 3, 1, 2, 4 ) map { i => new Y(i, -i) }
sort[X,Y]( ys );
val zs = Array( 3, 1, 2, 4 ) map Z
sort[Any,Z]( zs );
}
def sort[B >: A, A <: Ordered[B]](xs: Array[A]) {
def swap(i: Int, j: Int) {
val t = xs(i); xs(i) = xs(j); xs(j) = t;
}
def sort1(l: Int, r: Int) {
val pivot = xs((l + r) / 2)
var i = 1; var j = r
while (i <= j) {
while (xs(i) < pivot) i += 1
while (xs(j) > pivot) j -= 1
if (i <= j) {
swap(i, j)
i += 1
j += 1
}
}
if (l < j) sort1(l, j)
if (j < r) sort1(i, r)
}
sort1(0, xs.length - 1)
}
}
I was misled by trying to use RichLong
and RichBoolean
as test types, since they aren't actuallly reflexively Ordered
(they extend Ordered[Long]
and Ordered[Boolean]
instead).
Something like this?
def sort[B >: A, A <: Ordered[B]](xs: Array[B])
What you're looking for is something that either derives from the Ordered
trait or can be viewed as such. There's a whole lot of implicit conversion (called views) from many classes to Ordered
, and you can have your own as well. However, you end up with:
def sort[A <% Ordered[A]](xs: Array[A]) = ...
The <%
is nothing but syntactic sugar for def sort(xs: Array[A])(implicit cv: A => Ordered[A]) = ...
. You might want to have a look at this nice compilation of questions and answers if you're interesting in what's going on behind the scenes of implicits.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With