98 votes

Pourquoi le jeu immuable de Scala n'est-il pas covariant dans son type?

EDIT : reformulé cette question sur la base de la réponse originale

La classe scala.collection.immutable.Set n'est pas covariante dans son paramètre de type. Pourquoi est-ce?

 import scala.collection.immutable._

def foo(s: Set[CharSequence]): Unit = {
    println(s)
}

def bar(): Unit = {
   val s: Set[String] = Set("Hello", "World");
   foo(s); //DOES NOT COMPILE, regardless of whether type is declared 
           //explicitly in the val s declaration
}
 

57voto

Daniel Spiewak Points 30706

Set est invariant dans son paramètre de type, car le concept derrière les ensembles de fonctions. Les signatures suivantes devraient clarifier un peu les choses:

trait Set[A] extends (A=>Boolean) {
  def apply(e: A): Boolean
}

Si Set ont été covariants en A, apply méthode serait pas en mesure de prendre un paramètre de type A en raison de la contravariance des fonctions. Set pourrait être contravariant en A, mais cela provoque des problèmes lorsque vous voulez faire les choses comme ceci:

def elements: Iterable[A]

En bref, la meilleure solution est de garder les choses invariant, même pour les données immuables de la structure. Vous remarquerez qu' immutable.Map est également invariante dans l'un de ses paramètres de type.

53voto

Seth Tisue Points 9090

sur http://www.scala-lang.org/node/9764 Martin Odersky écrit:

"Sur la question des ensembles, je pense que la non-variance découle également des implémentations. Les ensembles communs sont implémentés sous la forme de tables de hachage, qui sont des tableaux non-variantes du type clé. Je conviens que c'est une irrégularité légèrement gênante."

Donc, il semble que tous nos efforts pour construire une raison de principe à ce sujet aient été erronés :-)

6voto

Jorge Ortiz Points 3374

EDIT: pour tous ceux qui demandent pourquoi cette réponse semble un peu hors-sujet, c'est parce que j'ai (l'interlocuteur) ont modifié la question.

Scala est l'inférence de type est assez bon pour comprendre que vous voulez CharSequences et pas des Chaînes dans certaines situations. En particulier, les ouvrages suivants, pour moi, dans 2.7.3:

import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")

Comment créer immuable.HashSets directement: ne pas. Comme une mise en œuvre de l'optimisation, immuable.HashSets de moins de 5 éléments ne sont pas réellement des instances de immuable.HashSet. Ils sont soit EmptySet, Set1, Set2, Set3, ou Set4. Ces classes sous-classe immuable.Ensemble, mais pas immuable.HashSet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X