In particular, this minimal example:
trait A[T1, T2] {
def convert(t1: T1): T2
def reverse(t2: T2): T1
}
class B extends A[Int, Double] {
def convert(i: Int): Double = i.toDouble
def reverse(i: Double): Int = i.toInt
}
class C extends A[Int, Float] {
def convert(i: Int): Float = i.toFloat
def reverse(i: Float): Int = i.toInt
}
val bOrC: A[Int, _] = if (System.nanoTime % 2 == 0) {
new B
} else {
new C
}
bOrC.convert(7)
bOrC.reverse(bOrC.convert(7))
Will fail on the last line:
scala> bOrC.reverse(bOrC.convert(7))
<console>:12: error: type mismatch;
found : (some other)_$1(in value bOrC)
required: _$1(in value bOrC)
bOrC.reverse(bOrC.convert(7))
It seems that the type of _$1
is the same in both the return type and the argument - it's bOrC
's T2
type, whatever it may be. Local type inference shouldn't be a problem here. Why can't I do this?
Is there a workaround that isn't as ugly as the following?
trait A[T1, T2] {
def convert(t1: T1): T2
def reverse(t2: X): T1
type X = T2
}
// ... rest as before
bOrC.reverse(bOrC.convert(7).asInstanceOf[bOrC.X])
Edit: looks like if you tell Scala it's the same type, everything is handled. This gets rid of the silly type X
:
def thereAndBack[T2](a: A[Int, T2], b: Int) = a.reverse(a.convert(b))
thereAndBack(bOrC)