2016-08-28 3 views
0

В частности, это минимальный пример:Почему Scala не отслеживает анонимные типы?

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

потерпит неудачу на последней строке:

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

кажется, что тип _$1 одинакова в обоих возвращаемый тип и аргумент - это bOrCT2 тип, каким бы он ни был. Локальный тип вывода не должен быть проблемой здесь. Почему я не могу это сделать?

Есть ли обходной путь, который не такой уродливый, как следующее?

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: выглядит, как если бы вы сказать Scala это тот же самый тип, все обрабатывается. Это избавляется от глупой type X:

def thereAndBack[T2](a: A[Int, T2], b: Int) = a.reverse(a.convert(b)) 
thereAndBack(bOrC) 
+1

Подчеркивание в этом контексте не является «анонимным типом», что это _existential типа _-- означает, что вы хотите сказать, компилятор вы _don't care_, что типа есть, поэтому компилятор будет счастливо лечить это как таковое. –

+0

Там есть диссонанс между вашим требованием запоминания типа и использования экзистенциального типа, который делает точно противоположное тому, что вы хотите. –

+0

@ m-z ОК, да, мне все равно, какой это тип. Но это тот же тип, который возвращается и используется, что бы это ни было. Там что-то не хватает. – VF1

ответ

0

Возможно, вы можете относиться к A как и только класс типов имеют одну из B/C доступного неявно?

def convert[T1, T2](x: T1)(implicit a: A[T1, T2]): T2 = { 
    a.convert(x) 
} 

def reverse[T1, T2](x: T2)(implicit a: A[T1, T2]): T1 = { 
    a.reverse(x) 
} 

implicit val b = new B 
// or implicit val c = new C 

convert(7) 
reverse(convert(7)) 
+0

Спасибо за ответ, но я не думаю, что это решение не сработает. Вы заставляете один путь кода иметь одно поведение, но это решение не будет работать, если оно зависит от определенного значения времени исполнения (например, 'System.nanoTime' в моем примере). Кроме того, это не совсем ответ на вопрос _why_. – VF1

+0

Я думаю, почему вопросы запрещены; только как вопросы, IIUC. –

+0

@ som-snytt Это изменение от нескольких вопросов, которые я задал раньше, и это еще не было указано мне. Вы ссылаетесь на что-то в FAQ? – VF1

Смежные вопросы