2014-09-20 2 views
0

Является ли следующее ожидаемое поведение или ошибка в Scala?Scala параметризованный общий параметр

СЛУЧАЙ 1:

class X[T1, T2] 
class XExt[T1, T2] extends X[T1, T2] 
class Y[T[t1] <: X[t1, _]] 
class YExt extends Y[XExt] 

приводит Ошибка: Xext принимает два параметра типа, как ожидается: один

class YExt extends Y[XExt] 
        ^

Но следующие пробегов OK:

class X[T1, T2] 
class XExt[T1, T2] extends X[T1, T2] 
class Y[T[t1, t2] <: X[t1, t2]] 
class YExt extends Y[XExt] 

Сведение к минимуму числа параметров могло бы ify код типа type params: тип T [t1] <: X [t1, _].

СЛУЧАЙ 2:

class X[T1, T2] 
class Y[T[t1, t2] <: X[t1, t2]] 
class Z[T <: Y[_]] 

приводит Ошибки: _ $-не принимают никаких параметров типа, ожидаемые: два

class Z[T <: Y[_]] 
      ^

Но как избежать определения параметров Y, если я не требую их? Как и в:

class X[T1, T2] 
class Y[T <: X[_, _]] 
class Z[T <: Y[_]] 

СЛУЧАЙ 3:

trait A[T] 
trait B[T[t] <: A[t]] 
trait AExt extends A[Int] 
trait BExt extends B[AExt] 

приводит Ошибка: Aext не принимает никаких параметров типа, как ожидается: один

trait BExt extends B[AExt] 
        ^

Но почему компилятор запрашивает один параметр, если он уже поставлен? Это противоречие. А как подкласс B?


Такое поведение наблюдается в IntelliJ Scala плагин и Eclipse, Scala IDE. Так что, вероятно, работает компилятор Scala.

+1

Я не думаю, что вы можете, будучи 'Y [_]' вложенный выше вид с ограничением вам необходимо предоставить компиляции достаточно доказательств, что вы уважая это ограничение: класс 'Z [ S [t1, t2] <: X [t1, t2], T <: Y [S]] '. –

+0

@ Ende Neu: Да, но ограничение Y [T] такое же. T все же имеет те же границы. Я не вижу причин указывать T, если я этого не требую. И посмотрите CASE 3. Я только что добавил. –

+0

Нет, 'T' не имеет той же границы,' T' в классе, а второй во втором случае - два разных 'T', только потому, что они имеют одну и ту же букву, не означает, что они связаны. –

ответ

0

Причина недопонимания заключается в смешении понятия абстрактного типа и общего параметра. Ошибочное предположение заключалось в том, что параметры типа и общие параметры равны в правилах ограничений. Смотри ниже. T1 и T2 класса Z эквивалентны. Но в ZExt они могут быть определены с помощью классов XExt1 и XExt2, которые имеют разное количество параметров. Второй параметр XExt2 просто игнорируется. Я ожидал, что реализация одной и той же логики с generics позволит использовать тот же синтаксис. То естьZ1 будет принимать XExt1, а также XExt2 (например, T1 и T2 в Z). Но он принимает только XExt1. Размещение XExt2 в качестве параметра приводит к ошибке.

И, честно говоря, до сих пор не понимаю, почему бы не дать дженерикам свободу типов. То есть почему бы не позволить XExt2 быть параметром Z1, позволяя компилятору выводить типы параметров XExt2 и просто игнорировать его второй параметр.

class X[T1, T2] 
class XExt1[T1] extends X[T1, Int] 
class XExt2[T1, T2] extends X[T1, T2] 

class Z { 
    type T1[t] <: X[t, _] 
    type T2[t] <: X[t, _] 
} 
class ZExt extends Z { 
    type T1[t] = XExt1[t] 
    type T2[t] = XExt2[t,_] 
} 

// But... 
class Z1[T[t] <: X[t, _]] 
class ZExt1 extends Z1[XExt1] 
class ZExt2 extends Z1[XExt2] // Error: XExt2 takes two type parameters, expected: one 

Ответы на случаях:

Случай 1:

Класс, который расширяет класс Y должен точно соответствовать Т [T] (с одним парам), который является, например, :

class X[T1, T2] 
class XExt[T1] extends X[T1, Int] 
class Y[T[t1] <: X[t1, _]] 
class YExt extends Y[XExt] 

СЛУЧАЙ 2:

Как @Ende Neu упоминается дополнительные параметры, который соответствует ограничению T [t1, t2] класс Y делает свою работу:

class X[T1, T2] 
class Y[T[t1, t2] <: X[t1, t2]] 
class Z[S[t1, t2] <: X[t1,t2], T <: Y[S]] 

К сожалению, T [t1, t2] наклоняет быть описан с подчеркиванием синтаксиса, как @ Самбетс предлагает. Компилятор предупреждает с "Wrong декларации сверху заявление":

class Z[T <: Y[_[_, _]]] 

Случай 3:

Та же проблема, как и в случае 1. Aext должны иметь один из параметров. Например:

trait A[T] 
trait B[T[t] <: A[t]] 
trait AExt[T] extends A[T] 
trait BExt[T] extends B[AExt] 
1

Дело 1: вы сказали Y берет тип с 1 параметром, но вы дали ему тип с двумя.

Случай 2: Похоже, попробуйте Z[T <: Y[_[_,_]]]

Случай 3: Вы сказали, что B принимает тип с 1 парам, но вы дали ему тип с двумя.

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

+0

Короткий ответ не всегда означает правильный ответ. Но спасибо за попытку. Ответ 1: Вы можете объявить «тип T [t1] <: X [t1, _]». Каков главный барьер, который нельзя делать в объявлении общих параметров? Ответ 2: Попробовали ли вы это предложить? («Неверное объявление верхней инструкции») Ответ 3: Ни одно из выражений CASE 3 не имеет двух параметров. Действительно, CASE 3 является самым странным. Кажется, что AExt соответствует ограничению T [t] <: A [t], где t - Int. Если вы замените generics на абстрактные типы, все эти выражения будут скомпилированы без ошибок. –

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