首页 > 解决方案 > 与路径投影混淆

问题描述

这是我想要做的

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”正是我想要的,但这并不能编译。有没有办法在这里做我想做的事?

更新

也许,我过度简化了用例。比方说,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,这似乎是多余的。

标签: scalatype-projection

解决方案


当您调用fooX(bar.x, bar)时,编译器只看到:

  • bar: Bar[_]这与bar : Bar[X] forSome { type X }
  • bar.x : X forSome { type X },这减少到bar.x: Any

然后它无法证明与中Any的相同。但是,如果将未知类型绑定到变量,则编译器会看到:XforSome { type X }p

  • bar: Bar[p]
  • bar.x : p
  • fooX[p](bar.x, bar)适用。

因此,这有效:

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

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

class Baz[R <: Bar[_]](bar: R){
  bar match {
    case b: Bar[p] => fooX[p](b.x, b)
  }
}

Outtakes(更新前尝试)

尝试解决原始问题的两个片段,也许你在这里找到一些有用的东西:

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 }

推荐阅读