Почему 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.