Как использовать подстановочный знак для старшего типа в Scala? - PullRequest
6 голосов
/ 21 ноября 2010

Допустим, у меня есть эта черта

trait Ctx[C, V[_]]

Я не могу создать сигнатуру метода, которая принимает Ctx, для которого параметр второго типа не указан (подстановочный знак).Например:

def test(c: Ctx[_, _]) = ()

не компилируется ("error: _$2 takes no type parameters, expected: one").Я также не могу сделать

def test(c: Ctx[_, _[_]]) = ()

("error: _$2 does not take type parameters").Чего мне не хватает?

Ответы [ 3 ]

5 голосов
/ 21 ноября 2010

Я могу определить это:

def test[V[X]](c:Ctx[_,V]) {}

И вроде бы нормально работает с выводом типа:

scala> trait Ctx[ C, V[ _ ]]
defined trait Ctx

scala> def test[V[X]](c:Ctx[_,V]) {}
test: [V[X]](c: Ctx[_, V])Unit

scala> class P extends Ctx[Int, List]
defined class P

scala> new P
res0: P = P@1f49969

scala> test(res0)

Редактировать : Я подозреваю, что не будет практичным заменить Ctx на использование абстрактного типа, но это то, что я смог сделать:

trait Ctx[C] { type V[X] }
class CtxOption[C] extends Ctx[C] { type V[X] = Option[X] }
class CtxList[C] extends Ctx[C] { type V[X] = List[X] }

def test(ctx:Ctx[_]) { println(ctx) }

val ctxOptInt = new CtxOption[Int]
val ctxListStr = new CtxList[String]

test(ctxOptInt)
test(ctxListStr)

val list = collection.mutable.ListBuffer[Ctx[_]]()
list += ctxOptInt
list += ctxListStr
list

Использование абстрактного типа для V избавляет вас от сложной (или невозможной) задачи определения синтаксиса параметра типа для конструктора подстановочного типа. Кроме того, как показано в примере ListBuffer , вы можете обрабатывать объекты, в которых V является конструктором другого типа ( Option и List в моем примере). Первое решение, которое я предоставил, не позволило бы вам сделать это.

Редактировать 2 : Как насчет?

trait AbstractCtx[C] { type W[X] }
trait Ctx[C,V[_]] extends AbstractCtx[C] { type W[X] = V[X] }
def test(ctx:AbstractCtx[_]) { println(ctx) }
3 голосов
/ 22 ноября 2010

Вам необходимо передать конструктор типа для второго аргумента Ctx. Scala не может вывести правильный вид, если вы просто передадите _. Также невозможно определить конструктор типа с помощью символов подстановки (т. Е. _[_]] на лету. Обратите внимание, что в вашем первом примере _$2 в сообщении об ошибке относится к типу, переданному как второй аргумент Ctx в целом. однако во втором примере _$2 относится к первому типу подстановочных знаков в _[_]. См. индикатор местоположения в сообщениях об ошибках:

<console>:6: error: _$2 does not take type parameters
       def test( c: Ctx[ _, _[ _ ]]) {}
                            ^

Следующие работы так как здесь V является конструктором типа правильного вида, ожидаемого Ctx.

def test[V[_]]( c: Ctx[ _, V]) {}
0 голосов
/ 11 декабря 2014

Это все объяснено здесь .Сфокусируйтесь на разделе «Общие ловушки» внизу.

...