Scala 为什么发电机组声明具有不变类型参数?

Scala 为什么发电机组声明具有不变类型参数?,scala,scala-collections,Scala,Scala Collections,我有一个Foo类型,带有子类型 我还有一个类,其中包含一个Foo: class FooResult(val foo: Foo ... 我有一组FooResult,我想用map()从中提取Foos,然后计算该组(Foos)和另一组Foos之间的差异。”下面的“结果”是一个集合[FooResult],-这是一个关键部分-bundle是一个集合[\up>这是一个有意识的设计决策,以使Set.contains/apply typesafe。您不应该拥有一个s:Set[Int]并意外地执行类似s.con

我有一个Foo类型,带有子类型

我还有一个类,其中包含一个Foo:

class FooResult(val foo: Foo ...

我有一组FooResult,我想用map()从中提取Foos,然后计算该组(Foos)和另一组Foos之间的差异。”下面的“结果”是一个集合[FooResult],-这是一个关键部分-bundle是一个集合[\up>这是一个有意识的设计决策,以使Set.contains/apply typesafe。您不应该拥有一个s:Set[Int]并意外地执行类似s.contains(“x”)的操作,因为它总是错误的,所以可能不是您想要的。另外,Set[T]实现函数[T,Boolean],只有在apply方法不采用Any时才可能实现该函数

scala用户邮件列表上对此主题进行了无休止的讨论

以下是Paul Phillips在第二次讨论中的一段话,很好地总结了基本原理:

是的,应用(别名为contains)是Set的中心操作,而 contains确实是Seq上的“一些方法”

没人说你有时不想要协变集合,但总的来说, 它更有用。”

请注意,您始终可以通过隐式转换向集合添加协方差。这意味着,如果您有一个集合[Int]和一个接受集合[Any]的方法,它将工作。但这也意味着您现在可以意外调用集合[Int].contains(“x”),编译器将不会捕获错误(您将始终得到false)

scala>隐式def setiscovoridant[T,美国包含(“x”)
res0:Boolean=false
scala>val a:Set[Any]=s
a:集合[任何]=集合(1,2,3,4)

好的-你或其他人能给我举一些例子来说明我需要做的事情吗?需要建立新的集合吗?(我不认为casting可以做到这一点,即使我想这样做。)谢谢!我只是让代码与[Foo]的集合一起工作,而不是与[Foo]的集合一起工作[-
val completedFoos = results.map(result => result.calc)
val unfinishedFoos = bundle.foos.diff(completedCalcs)
type mismatch;
found   : Set[Foo]
required: scala.collection.GenSet[_$1]
Note: Foo >: _$1, but trait GenSet is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: _$1`. (SLS 3.2.10)
scala> implicit def setIsCovariant[T,U <: T](s:Set[U]):Set[T] = s.asInstanceOf[Set[T]]
setIsCovariant: [T, U <: T](s: Set[U])Set[T]

scala> val s : Set[Int] = Set(1,2,3,4)
s: Set[Int] = Set(1, 2, 3, 4)

scala> s.contains("x")
res0: Boolean = false

scala> val a: Set[Any] = s
a: Set[Any] = Set(1, 2, 3, 4)