Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Covariant Typeparameter in scala needs to be invariant in java interface

I've got a trait that looks like this (some further information can be found at this related question by myself although I don't think, it's needed for this question)

trait Extractor[-A,+B] {
  def extract(d:A):B
  //lots of other things
}

To use this in an existing java framework I would like this Extractor to either have a function that returns a Comparator[B] (being java.util.Comparator) or even better extend Comparator[A]. Now that poses a problem because Comparators type parameter is ought to be invariant, while A is contravariant and B is covariant.

So I get errors like this:

scala> import java.util.Comparator
import java.util.Comparator

scala> trait Extractor[-A,+B] extends Comparator[A]
<console>:6: error: contravariant type A occurs in invariant position in type [-A,+B]java.lang.Object with java.util.Comparator[A] of trait Extractor
       trait Extractor[-A,+B] extends Comparator[A]
             ^


scala> trait Extractor[-A, +B] {                 
     |   def comp:Comparator[B]
     | }
<console>:7: error: covariant type B occurs in invariant position in type => java.util.Comparator[B] of method comp
         def comp:Comparator[B]
             ^

Do you see any way out of this or is this just one of those cases where "using java generics in scala hurts"?

like image 370
Agl Avatar asked Sep 15 '10 09:09

Agl


2 Answers

With help of type-bounds it's possible to do the following:

scala> trait Extractor[-A, +B] {
     | def comp:Comparator[_ <: B]
     | }
defined trait Extractor
like image 130
Vasil Remeniuk Avatar answered Sep 17 '22 14:09

Vasil Remeniuk


You can make Extractor[A,B] extend Comparator[A] by using the @uncheckedVariance annotation.

scala> import scala.annotation.unchecked.uncheckedVariance
import scala.annotation.unchecked.uncheckedVariance

scala> trait Extractor[-A,+B] extends java.util.Comparator[A @uncheckedVariance]
defined trait Extractor

@uncheckedVariance is safe here because Comparator could have been defined as Comparator[-T]. There was a discussion around making Ordering covariant for Scala 2.8 using this annotation.

Edit See this question for more about @uncheckedVariance.

like image 23
Ben Lings Avatar answered Sep 17 '22 14:09

Ben Lings