嵌套集合中Option的奇怪类型擦除

geo*_*lgo 1 scala type-erasure scala-collections

在嵌套集合中有选项时遇到以下奇怪的问题:

val works: Array[Option[Int]] = Array(1)
  .map { t => Some(t)}

val fails: Array[Array[Option[Int]]] = Array(Array(1))
  .map { ts => ts.map { Some(_)} }
// error: type mismatch;  found   : Array[Array[Some[Int]]] required: Array[Array[Option[Int]]]

val worksButUgly: Array[Array[Option[Int]]] = Array(Array(1))
  .map { ts => ts.map { case t => (Some(t).asInstanceOf[Option[Int]])}}
Run Code Online (Sandbox Code Playgroud)

我想这可能是沿途某种类型擦除的问题,但它是否是Scala中的预期行为?有谁知道究竟发生了什么?

slo*_*ouc 5

Scala中的数组是不变的.这可以防止数组中存在的一些问题,例如Java,你可以在其中创建一些东西,将它宣告为某个类的超类数组,然后再放入另一个子类.例如,说苹果数组是一个数组水果,然后把香蕉放入.最糟糕的是,它在运行时失败,而不是在编译时.

出于这个原因,Scala决定数组应该是不变的.这意味着它Array[Apple]不是子类Array[Fruit].(注意,与数组不同,不可变集合通常是协变的,例如List,因为不变性阻止我们在以后放入任何香蕉)

是的 Some是的子类Option,但Array[Some]不是它的子类Array[Option].这些将起作用:

val foo1: Array[Array[Option[Int]]] = Array(Array(1))
  .map { ts => ts.map { Option(_)} }

val foo2: Array[List[Option[Int]]] = Array(List(1))
  .map { ts => ts.map { Some(_)} }
Run Code Online (Sandbox Code Playgroud)