Почему Scala неизменяемый набор не ковариант в своем типе?
EDIT: переписан этот вопрос на основе оригинального ответа
Класс scala.collection.immutable.Set
не является ковариантным в своем параметре типа. Почему это?
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
}
Ответы
Ответ 1
Set
является инвариантным по своему параметру типа из-за концепции за множествами как функций. Следующие подписи должны слегка прояснить ситуацию:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
Если Set
были ковариантными в A
, метод apply
не смог бы взять параметр типа A
из-за контравариантности функций. Set
потенциально может быть контравариантным в A
, но это также вызывает проблемы, когда вы хотите делать такие вещи:
def elements: Iterable[A]
Короче говоря, лучшим решением является сохранение инвариантности вещей даже для неизменной структуры данных. Вы заметите, что immutable.Map
также инвариантен в одном из его параметров типа.
Ответ 2
at http://www.scala-lang.org/node/9764 Мартин Одерский пишет:
"По вопросу о наборах, я считаю, что неравномерность также вытекает из реализаций. Общие наборы реализованы как hashtables, которые представляют собой невариантные массивы типа ключа. Я согласен с этим немного раздражающим нерегулярностью".
Итак, кажется, что все наши усилия по построению принципиальной причины для этого были ошибочными: -)
Ответ 3
EDIT: для кого-то интересно, почему этот ответ кажется слегка не по теме, это потому, что я (вопросник) изменил вопрос.
Scala вывод типа достаточно хорош, чтобы понять, что вы хотите CharSequences, а не Strings в некоторых ситуациях. В частности, следующие работы для меня в 2.7.3:
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
Как создать неизменяемые. HashSets напрямую: не надо. Как оптимизация реализации, неизменяемые. HashSets из менее чем 5 элементов не являются фактически экземплярами неизменяемых. HashSet. Это либо EmptySet, Set1, Set2, Set3, либо Set4. Эти подклассы классов неизменяемы. Установите, но не обязательно. HashSet.