2016-06-15 1 views
4

J'apprends Functional Programming Principles in Scala, comme je suis passé par la conférence Subtyping and Generics, j'ai eu une confusion au sujet de covariance:Covariance à Scala

Étant donné: NonEmpty <: IntSet ou NonEmpty est un sous-type de IntSet

Est-List[NonEmpty] <: List[IntSet] ou est-List[NonEmpty] un sous-type de List[IntSet]?

Et la réponse est logique car une liste d'ensembles non vides est un cas particulier d'une liste d'ensembles arbitraires. Cette réponse implique-t-elle que List[NonEmpty] est un sous-type de List[IntSet]?

J'ai donc essayé ceci:

val nonEmpty: List[NonEmpty] = null 
val intSet: List[IntSet] = nonEmpty 

Je suis une erreur de compilation:

Expression of type List[NonEmpty] doesn't conform to expected type List[IntSet]

Comme je sais que les médicaments génériques sont invariantes en Java, sont génériques covariantes dans Scala ou j'ai mauvaise compréhension à propos de la convariance?

Edit:

Voici les définitions de IntSet, NonEmpty, List:

abstract class IntSet { 
    def contains(x: Int): Boolean 
    def incl(x: Int): IntSet 
    def union(other: IntSet): IntSet 
} 

class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet {...} 

trait List[T] { 
    def isEmpty: Boolean 
    def head: T 
    def tail: List[T] 
} 
+0

Ceci devrait être compilé (en supposant que vous utilisiez la 'Liste' Scala standard). Quelles sont les définitions de 'NonEmpty' et' IntSet'? –

+0

@AlexeyRomanov: Je change de liste Scala et il est conforme, mais je ne comprends pas pourquoi, ne sont-ils pas les deux types génériques. – toandv

+1

'scala.collection.immutable.List [+ A]' est covariant sur 'A' comme indiqué par le symbole' + '. –

Répondre

2

Le problème est dans la définition de List; son paramètre de type n'est pas préfixé d'un + pour indiquer que le paramètre de type est covariant. Changez-le en:

trait List[+T] { 
    def isEmpty: Boolean 
    def head: T 
    def tail: List[T] 
} 
3

D'abord, vous devez savoir est que

In Scala, however, generic types have by default nonvariant (or, "rigid") subtyping

covariance signifie que

if S is a subtype of type T, then should List[S] be considered a subtype of List[T]

nonvariant a un autre sens que

if S is a subtype of type T, then should List[S] not be considered a subtype of List[T]

Le document vous aidera. Il suffit de rechercher le mot covariance, alors vous trouverez la réponse à votre question.

Avoir une bonne chance