2012-05-16 4 views
6

Я пытаюсь параметризовать некоторые методы с очень общими параметрами типа.Типы Scala: минимальные верхние границы

В качестве примера, в РЕПЛ я сначала определить:

trait Term 
case class FunctionalTerm[+T <: Term](t: T) extends Term 

Наглядно, следующий метод принимает срок и FunctionalTerm, и возвращает что-то с типом верхней границей типа термина прошел и тип аргумента FunctionalTerm:

def ex1[T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3): R = sys.error("TODO") 

Пока что так хорошо в REPL.

Тогда я определяю ex2 в качестве вспомогательной функции, которая выполняет ту же операцию, как ex1, но входные аргументы местами:

def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2,s) 

Попытка определить ex2 в РЕПЛ дает следующее сообщение об ошибке:

error: inferred type arguments [T2,T3,FunctionalTerm,T3,T3] do not conform to method ex1's type parameter bounds [T1 <: Term,T3 <: X,FunctionalTerm[T1] <: X,X <: R,R <: Term] 
     ex1(t2,s) 
     ^
error: type mismatch; 
found : FunctionalTerm[T2] 
required: FunctionalTerm[T1] 
     ex1(t2,s) 
      ^
error: type mismatch; 
found : T3(in method ex2) 
required: T3(in method ex1) 
     ex1(t2,s) 
       ^
error: type mismatch; 
found : R(in method ex1) 
required: R(in method ex2) 
     ex1(t2,s) 
      ^

Я потратил около двух дней, пытаясь найти решение, и теперь я полностью застрял. Я больше ничего не могу найти в Google.

Поскольку список аргументов типа из ex2 такой же, как и ex1 но с T1 и T2 поменялись местами, я не понимаю, это не так, и как это исправить.

Любая помощь была бы чрезвычайно оценена!

Обновление

Наименее верхние границы были красная сельдь. Пример может быть дополнительно удален.

Следующие две функции могут быть определены в РЕПЛ без ошибок:

def ex1[T1 <: Term, FunctionalTerm[T1] <: Term](t1: FunctionalTerm[T1]): Term = sys.error("TODO: ex1") 
def ex2[T2 <: Term, FunctionalTerm[T2] <: Term](t2: FunctionalTerm[T2]): Term = ex1(t2) 

Вводя дополнительный параметр X, кажется, вызывает проблему. Я могу определить следующее в РЕПЛ:

def ex3[T1 <: Term, FunctionalTerm[T1] <: X, X <: Term](t1: FunctionalTerm[T1]): Term = sys.error("TODO: ex3") 

Но попытка впоследствии определить:

def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 

выдает ошибку:

error: inferred type arguments [T2,FunctionalTerm,Nothing] do not conform to method ex3's type parameter bounds [T1 <: Term,FunctionalTerm[T1] <: X,X <: Term] 
     def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 
                          ^
error: type mismatch; 
found : FunctionalTerm[T2] 
required: FunctionalTerm[T1] 
     def ex4[T2 <: Term, FunctionalTerm[T2] <: X, X <: Term](t2: FunctionalTerm[T2]): Term = ex3(t2) 
                           ^

Итак, я предполагаю, что возникает вопрос: Почему параметр X, не использованный в сигнатуре, имеет этот эффект?

+0

Я забыл сказать, что я использую Scala 2.10-M3. –

+0

Вы не используете более высокие виды, хотя :-) –

+0

@oxbow_lakes Oh ... Я исправлю –

ответ

5

Я не уверен, что вы испытываете ошибку, но я уверен, что вы делаете свою жизнь намного сложнее, чем это должно быть. Вы можете рассчитывать на ковариации и унификации делать всю тяжелую работу за вас,

scala> trait Term 
defined trait Term 

scala> case class FunctionalTerm[+T <: Term](t: T) extends Term 
defined class FunctionalTerm 

scala> def ex1[T <: Term](t1 : FunctionalTerm[T], s : T) : T = s 
ex1: [T <: Term](t1: FunctionalTerm[T], s: T)T 

scala> class A extends Term ; class B extends A ; class C extends A 
defined class A 
defined class B 
defined class C 
scala> ex1(new FunctionalTerm(new B), new C) 
res0: A = [email protected] 

примечания распознанного типа результата (что эквивалентно R от оригинала более сложного определение) ... это A, который является LUB от B и C.

Теперь перевернутый версия тривиально и просто работает,

scala> def ex2[T <: Term](s : T, t1 : FunctionalTerm[T]) : T = s 
ex2: [T <: Term](s: T, t1: FunctionalTerm[T])T 

scala> ex2(new C, new FunctionalTerm(new B)) 
res1: A = [email protected]522ddcec 
+1

Оказалось, что сообщаемое поведение НЕ является ошибкой. Используя FunctionalTerm [T1] <: X и FunctionalTerm [T2] <: X в исходном примере объявлен параметр типа метода, называемый FunctionalTerm, который не имеет отношения к классу case с тем же именем. Я отмечаю это как ответ, однако, поскольку то, что было предложено, достигло того, что мне нужно было сделать. –

+0

Ну, дух! ... удивительно, что ни я, ни @oxbow_lakes не заметили этого! –

2

Я собираюсь упростить ваш пример (я использую 2.9.1):

scala> trait Term; case class FunctionalTerm[+T <: Term](t: T) extends Term; 
defined trait Term 
defined class FunctionalTerm 

scala> def ex1[T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3): R = sys.error("TODO") 
ex1: [T1 <: Term, T3 <: X, FunctionalTerm[T1] <: X, X <: R, R <: Term](t1: FunctionalTerm[T1], s: T3)R 

Теперь декларирование второго метода:

scala> def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2, s) 
<console>:11: error: inferred type arguments [T2,T3,FunctionalTerm,T3,T3] do not conform to method ex1's type parameter bounds [T1 <: Term,T3 <: X,FunctionalTerm[T1] <: X,X <: R,R <: Term] 
     def ex2[T2 <: Term, T3 <: X, FunctionalTerm[T2] <: X, X <: R, R <: Term](s: T3, t2: FunctionalTerm[T2]): R = ex1(t2, s) 
                                ^

В подозрительном вещи (для меня) это выводимые типов [T2,T3,FunctionalTerm,T3,T3] - в частности FunctionalTerm. FunctionalTerm является конструктором типа * -> *, но метод ожидает тип * в этом положении.

Я бы сказал, что это (предположительно) ошибка, и, следовательно, вы должны представить его в список рассылки Scala-пользователя (перед поднятием билета) - Адриаана Мавров и Miles Сабина гораздо более вероятно, подробный ответ о том, прав ли я.

+0

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