Почему неизменяемый набор Scala не является ковариантным по своему типу?

StackOverflow https://stackoverflow.com/questions/676615

Вопрос

РЕДАКТИРОВАТЬ:Переписал этот вопрос на основе оригинального ответа

А 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top