证明泛型类型的上限类型

jam*_*rta 0 generics types scala

我有一个类型类,我想用它来存储一种对象:

trait RetainType {
  type A
}

object RetainType {
  def apply[A0](): RetainType = new RetainType{
    type A = A0
  }
}
Run Code Online (Sandbox Code Playgroud)

鉴于以下课程:

trait Annotation
class Entity extends Annotation
Run Code Online (Sandbox Code Playgroud)

我想编译器证明RetainType.A扩展Annotation:

def hasAnnotation[A <: Annotation] = Unit
Run Code Online (Sandbox Code Playgroud)

但是使用RetainType编译器似乎无法解决这个问题:

val retainType = RetainType[Entity]
hasAnnotation[RetainType.A] //throws an error: type arguments [retainType.A] do not conform to method hasAnnotation's type parameter bounds [A <: Annotation]
Run Code Online (Sandbox Code Playgroud)

如果指定了类型,它可以正常工作:

hasAnnotation[Entity] //works fine
Run Code Online (Sandbox Code Playgroud)

无论如何编译器可以证明这种关系?

HTN*_*TNW 5

你弄乱了以下的签名RetainType.apply:

def apply[A0](): RetainType
Run Code Online (Sandbox Code Playgroud)

返回类型没有提及A0,因此它被"遗忘".也就是说,在

val x = RetainType[Int]
Run Code Online (Sandbox Code Playgroud)

x.A是完全抽象的; 编译器无法证明x.A = Int因为apply签名会删除该信息.使用细化类型:

object RetainType {
  def apply[A0](): RetainType { type A = A0 } = new RetainType { override type A = A0 }
}
Run Code Online (Sandbox Code Playgroud)

您可能希望使用该Aux模式使这个更好用:

object RetainType {
  type Aux[A0] = RetainType { type A = A0 }
  def apply[A0](): RetainType.Aux[A0] = new RetainType { override type A = A0 }
}
Run Code Online (Sandbox Code Playgroud)