Scala Set,不变类型会发生什么?

时间:2016-10-13 10:14:06

标签: scala invariance

在scala应用程序中执行重构时遇到了一种情况,即从List更改为Set会引发一个我之前没有过的问题。我对方差有一些了解,但我想了解它对编译器的意义。

我有类似的东西,编译和工作得很好:

case class MyClassList(s: List[Any])
val myList = List(("this", false)) // List[(String, Boolean)]
val listWorks = MyClassList(myList)

然后我将列表更改为:

case class MyClassSet(s: Set[Any])
val mySet = Set(("this", false)) // Set[(String, Boolean)]
val setFails = MyClassSet(mySet)

此时,创建一个MyClassSet类型的对象已经不再适合我将一个Set作为参数传递,即使它接受一个Set of Any。现在,当以下工作时,它有点令人困惑(请注意,该集合是"与之前的mySet相同")

val setWorks1 = MyClassSet(Set(("this", false)))

我认为简单的解释是编译器将mySet val推断为Set [(String,Boolean)],但是当我直接在setWorks1的参数列表中实例化它时,因为它接受Set [Any],编译器将其推断为Set [Any]。这使得第一个示例失败,第二个示例通过。这些也有效,这表明以前是正确的:

val setWorks2 = MyClassSet(mySet.toSet[Any])
val mySetOfAny: Set[Any] = Set(("this", false), ("that", true), ("other", false))
val setWorks3 = MyClassSet(mySetOfAny)

编译器显示的实际错误是:

Error:(15, 55) type mismatch;
found   : Set[(String, Boolean)]
required: Set[Any]
Note: (String, Boolean) <: Any, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: (...)

列表和集合定义如下:

type List[+A]  = scala.collection.immutable.List[A]
type Set[A]    = immutable.Set[A]
  • 类型方差的差异是否允许我传递一个比任何&#34;更受限制的类型的列表?作为论点,但不是在案件中 设置?
  • 这种区别只会阻止类型之间的转换或转换吗?
  • 这主要是编译器&#34;限制&#34;或者是一种不变类型的预期财产?
  • 不变类型之间是否存在其他差异&#34;在实践中&#34;或者他们归结为像这样的铸造?

1 个答案:

答案 0 :(得分:0)

1)这里解释:     Why is Scala's immutable Set not covariant in its type?

基本上,Set [T]也是Function1[T, Boolean]Function1的签名为[-In, +Out],因此{1}} T+T-T不同,因为scala不会允许双变量(它会显着削弱类型系统)。

2)您可以使用.toSet[Any]asInstanceOf上的包装器)轻松地投射它。还有一种方法skip variance check

3,4)它是通用(多态)类型的预期属性。它们可以是不变的/协变的/逆变的(不仅仅是),而且它是由简单的规则正式描述的。您可以在此处阅读说明:https://stackoverflow.com/a/27627891/1809978