jamborta jamborta - 3 years ago 172
Scala Question

Prove upper type bound for generic types

I have a type class which I'd like to use to store a type of an object:

trait RetainType {
type A

object RetainType {
def apply[A0](): RetainType = new RetainType{
type A = A0

Given the following class:

trait Annotation
class Entity extends Annotation

I would like the compiler to prove that

def hasAnnotation[A <: Annotation] = Unit

But using
the compiler does not seem to resolve this:

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]

It works ok if the type is specified:

hasAnnotation[Entity] //works fine

Anyway the compiler can prove this relation?

Answer Source

You messed up the signature of RetainType.apply:

def apply[A0](): RetainType

The return type does not mention A0, so it is "forgotten". That is, in

val x = RetainType[Int]

x.A is completely abstract; the compiler cannot prove that x.A = Int because apply's signature erased that information. Use a refinement type:

object RetainType {
  def apply[A0](): RetainType { type A = A0 } = new RetainType { override type A = A0 }

You may want to use the Aux pattern to make this nicer to work with:

object RetainType {
  type Aux[A0] = RetainType { type A = A0 }
  def apply[A0](): RetainType.Aux[A0] = new RetainType { override type A = A0 }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download