Путаница с проекциями пути - PullRequest
0 голосов
/ 02 июня 2018

Вот что я пытаюсь сделать

class Bar[P](val x: P) { type Foo = P }
class Baz[R <: Bar[_]](bar: R) { val x: R#Foo = bar.x }

Идея состоит в том, чтобы создать Baz с одним параметром типа и иметь доступ к обоим типам внутри него.

Но это не работает: (

found   : Baz.this.x.type (with underlying type _$1)
required: _$1

Звучит так, будто «базовый тип _ $ 1» - именно то, что я хочу, но это не компилируется. Есть ли способ сделатьчто я хочу здесь?

update

Возможно, я упростил вариант использования. Допустим, Bar на самом деле что-то вроде этого:

trait Foo[T] { def doStuff(t: T) = ??? }
class Bar[P] extends Foo[P](val x: P) { type Foo = P }

и где-то еще у меня есть

 def fooX[T](x: T, foo: Foo[T]) = foo.doStuff(x)

, и я хочу вызвать его с Baz:

 class Baz[R <: Bar[_]](bar: R) { fooX(bar.x, bar) }

Такое ощущение, что оно должно работать: fooX параметры будутвсегда иметь правильный тип. Но он не компилируется, и я не могу придумать лучшего обходного пути, чем иметь два параметра типа для Baz, что кажется избыточным.

1 Ответ

0 голосов
/ 02 июня 2018

Когда вы вызываете fooX(bar.x, bar), компилятор видит только:

  • bar: Bar[_], что совпадает с bar : Bar[X] forSome { type X }
  • bar.x : X forSome { type X }, что уменьшает до bar.x: Any

, а затем не удается доказать, что Any совпадает с X в forSome { type X }.Однако, если вы связываете неизвестный тип с переменной p, то компилятор видит:

  • bar: Bar[p]
  • bar.x : p
  • fooX[p](bar.x, bar)Применимокоторый пытался решить исходный вопрос, может быть, вы найдете что-то полезное здесь:
    class Bar[P](val x: P) { type Foo = P ; val y: Foo = x }
    class Baz[R <: Bar[_]](val bar: R) { val x: bar.Foo = bar.y }
    

    другой способ связать x с Foo:

    trait Br { type Foo ; val x: Foo }
    class Bar[F](val x: F) extends Br { type Foo = F }
    class Baz[R <: Br](val bar: R) {val x: bar.Foo = bar.x }
    
...