2017-10-09 2 views
10

Considérez l'extrait suivant:Impossible déduire paramètre contravariante type Rien

trait X[-T] 
object Y extends X[Nothing] 
def a[T](x: X[T]): X[T] = x 
a(Y) 

Compilation de ce qui précède (2.12.3) échoue avec:

type mismatch; 
found : Y.type 
required: X[T] 
    a(Y) 
    ^

Cette compile bien si:

  • un type différent de Nothing est utilisé (par exemple object Y extends X[String])
  • la méthode a n'utilise pas T dans son type de retour (par ex. def a[T](x: X[T]): Unit = {})
  • le paramètre de type pour a est explicitement donnée (à savoir a[Nothing](Y))
  • T est covariant, pas contravariante (échoue également si elle est invariante)

Est-ce une cas particulier dans le compilateur pour Nothing?

En tant, le semble après un travail autour de "intéressant" pour bien fonctionner:

trait X[-T] 
object Y extends X[Nothing] 
def a[T, U <: T](x: X[T]): X[U] = x 
a(Y) 

Répondre

1

Je vais essayer d'expliquer la ligne de code en ligne

Ligne 1: trait X[-T] -> trait X est contravariant dans le type T. Donc vous pouvez remplacer n'importe quelle variable de type X [T] par son sous-type. En cas de types contravariants, Z [A] est un sous-type de Z [B] si B est un sous-type de A.

Ligne 2: object Y extends X[Nothing] -> l'objet Y est de type X [Nothing]. S'il vous plaît noter que rien n'est sous-type de tous les autres types.

Ligne 3: def a[T](x: X[T]): X[T] = x -> définir une expression qui prend des arguments de type X [T]. Puisque le trait X est contravariant dans le type T, vous pouvez également passer des sous-types de X [T] ie X [N] tel que T est sous-type de N

Ligne 4: a(Y) -> Appelez l'expression 'a' avec l'argument de type X [Rien]. Puisque le compilateur ne connaît pas le type d'argument de 'a', il ne peut pas décider si X [Nothing] est un sous-type de X [T]. Il y a plusieurs manières de résoudre ceci

Solution 1: `a[Nothing]` -> explicitly defining the type 

Solution 2: `tait X[+T]` -> make X covariant in type T. In this case Z[A] is subtype of Z[B] if A is subtype of B. This will work because Nothing is subtype of any other type 
+0

Merci pour la réponse, mais pourquoi utiliser 'String' au lieu de' Nothing' rend l'exemple compile? Ou pourquoi le work-around fonctionne-t-il? – adamw