2017-10-02 8 views
0

j'ai une classe de type que je voudrais utiliser pour stocker un type d'un objet:Prouver de type limite supérieure pour les types génériques

trait RetainType { 
    type A 
} 

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

Compte tenu de la classe suivante:

trait Annotation 
class Entity extends Annotation 

I souhaite que le compilateur de prouver que RetainType.A étend Annotation:

def hasAnnotation[A <: Annotation] = Unit 

Mais en utilisant RetainType le compilateur ne semble pas résoudre ce:

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] 

Il fonctionne bien si le type est spécifié:

hasAnnotation[Entity] //works fine 

Quoi qu'il en soit le compilateur peut prouver cette relation?

Répondre

5

Vous foiré la signature de RetainType.apply:

def apply[A0](): RetainType 

Le type de retour ne mentionne pas A0, il est donc "oublié". C'est-à-dire, dans

val x = RetainType[Int] 

x.A est complètement abstrait; le compilateur ne peut pas prouver que x.A = Int parce que la signature apply a effacé cette information. Utilisez un type de raffinement:

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

Vous pouvez utiliser le modèle Aux pour faire de ce plus agréable de travailler avec:

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

Ah, je vous remercie. J'ai raté ce petit bout. – jamborta