Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Beginner: How do I say "any superclass of generic A"

Tags:

generics

scala

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 Ints.

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).

like image 883
rampion Avatar asked Jan 20 '12 18:01

rampion


2 Answers

Something like this?

def sort[B >: A, A <: Ordered[B]](xs: Array[B]) 
like image 136
agilesteel Avatar answered Sep 20 '22 14:09

agilesteel


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.

like image 22
fotNelton Avatar answered Sep 20 '22 14:09

fotNelton