在scala类型层次结构中途忽略通用参数

时间:2019-04-30 22:57:45

标签: scala generics existential-type

我有一个相互平行的类型层次结构,这些层次结构通常相互引用:一个通过普通泛型,另一个通过类型变量。

但是,并行层次结构之一比另一个层次结构短,这导致了我的麻烦。

我在下面提供了一个代码段,并将编译器错误作为行内注释添加到导致问题的行上方:

  • type arguments [Foo[_],FooKey] do not conform to trait PrimaryKey's type parameter bounds [A <: Entity[A],B <: PrimaryKey[A,B]]
  • overriding type K in trait Entity with bounds <: PrimaryKey[A,Foo.this.K]; type K has incompatible type

问题是我希望FooKey不通用,因为FooKey对于参数Foo的实现有多精确都无关紧要。

package com.scalatest

object Database {
  trait PrimaryKey[A <: Entity[A], B <: PrimaryKey[A, B]] {
    this: B =>
  }

  trait Entity[A <: Entity[A]] {
    this: A =>

    type K <: PrimaryKey[A, K]
    val id: K
  }

  //Error:(17, 24) type arguments [com.scalatest.Database.Foo[_],com.scalatest.Database.FooKey] do not conform to trait PrimaryKey's type parameter bounds [A <: com.scalatest.Database.Entity[A],B <: com.scalatest.Database.PrimaryKey[A,B]]
  //  class FooKey extends PrimaryKey[Foo[_], FooKey]
  class FooKey extends PrimaryKey[Foo[_], FooKey]

  trait Foo[A <: Foo[A]] extends Entity[A] {
    this: A =>
    //Error:(24, 19) overriding type K in trait Entity with bounds <: com.scalatest.Database.PrimaryKey[A,Foo.this.K];
    // type K has incompatible type
    //    override type K = FooKey
    override type K = FooKey
  }

  class FooImpl(val id: FooKey) extends Foo[FooImpl]
}

我设法在声明Foo[_]中使用了存在性类型而不是FooKey,同时使所有A协变,但是我仍然遇到第二个错误

  class FooKey extends PrimaryKey[Foo[A] forSome { type A <: Foo[A] }, FooKey]

1 个答案:

答案 0 :(得分:1)

那不是真的

  

对于FooKey来说,Foo的实现参数的准确程度无关紧要。

您要使用FooKey覆盖类型K <: PrimaryKey[A, K],其中Atrait Entity[A <: Entity[A]] {...中的类型相同 而且您在trait Foo[A <: Foo[A]] {...中进行了覆盖,因此FooKey必须满足条件K <: PrimaryKey[A, K](这不仅是上限,因为K在两端都存在) },因此A <: Foo[A]应该被普遍地量化而不是存在地量化。

因此您应该将类​​型参数添加到FooKey

FooKey