Почему неизменяемый набор Scala не является ковариантным по своему типу?
-
21-08-2019 - |
Вопрос
РЕДАКТИРОВАТЬ:Переписал этот вопрос на основе оригинального ответа
А 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
}
Решение
Set
инвариантен в своем параметре типа из-за концепции, лежащей в основе множеств как функций.Следующие подписи должны немного прояснить ситуацию:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
Если Set
были ковариантными в A
, apply
метод не сможет принять параметр типа A
из-за контравариантности функций. Set
потенциально может быть контрвариантный в A
, но это тоже вызывает проблемы, когда вы хотите сделать что-то вроде этого:
def elements: Iterable[A]
Короче говоря, лучшее решение — сохранять неизменность, даже для неизменяемой структуры данных.Вы заметите это immutable.Map
также инвариантен в одном из параметров своего типа.
Другие советы
в http://www.scala-lang.org/node/9764 Мартин Одерски пишет:
«Что касается наборов, я считаю, что невариативность также связана с реализациями.Общие наборы реализованы в виде хеш-таблиц, которые представляют собой нонвариантные массивы ключевого типа.Я согласен, что это немного раздражающая неточность».
Так что, похоже, все наши попытки построить принципиальную причину этого были ошибочными :-)
РЕДАКТИРОВАТЬ:для тех, кто задается вопросом, почему этот ответ кажется немного не по теме, это потому, что я (задавший вопрос) изменил вопрос.
Вывод типов в 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.