РЕДАКТИРОВАТЬ : переписал этот вопрос на основе исходного ответа
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
}
scala
set
covariance
scala-collections
Oxbow_lakes
источник
источник
foo(s.toSet[CharSequence])
компилируется нормально.toSet
Метод является O (1) - это просто обертыванияasInstanceOf
.foo(Set("Hello", "World"))
компилируется и на 2.10, так как Scala, похоже, может определить правильный тип Set. Однако он не работает с неявными преобразованиями ( stackoverflow.com/questions/23274033/… ).Ответы:
Set
инвариантен в своем параметре типа из-за концепции, лежащей в основе множеств как функций. Следующие подписи должны немного прояснить ситуацию:trait Set[A] extends (A=>Boolean) { def apply(e: A): Boolean }
Если бы
Set
были ковариантнымиA
,apply
метод не смог бы принимать параметр типаA
из-за контравариантности функций.Set
потенциально может быть контравариантен вA
, но это тоже вызывает вопросы , когда вы хотите сделать что - то вроде этого:def elements: Iterable[A]
Короче говоря, лучшее решение - сохранить неизменность даже для неизменной структуры данных. Вы заметите, что
immutable.Map
это также инвариантно в одном из параметров типа.источник
List(1,2,3).contains _
is(Any) => Boolean
, а типSet(1,2,3).contains _
isres1: (Int) => Boolean
.на http://www.scala-lang.org/node/9764 Мартин Одерски пишет:
Итак, похоже, что все наши попытки найти принципиальную причину для этого были ошибочными :-)
источник
Seq
ковариантны ... Я что-то упускаю?Array[Any]
внутреннее хранилище .РЕДАКТИРОВАТЬ : для всех, кто задается вопросом, почему этот ответ кажется немного не по теме, это потому, что я (спрашивающий) изменил вопрос.
Вывод типа Scala достаточно хорош, чтобы понять, что в некоторых ситуациях вам нужны CharSequences, а не Strings. В частности, в 2.7.3 у меня работает следующее:
import scala.collections.immutable._ def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
Что касается того, как напрямую создать immutable.HashSets: не делайте этого. В качестве оптимизации реализации immutable.HashSets из менее чем 5 элементов на самом деле не являются экземплярами immutable.HashSet. Это либо EmptySet, Set1, Set2, Set3 или Set4. Эти классы являются подклассом immutable.Set, но не immutable.HashSet.
источник