嵌套集合中 Option 的奇怪类型擦除
Weird type erasure for Option in nested collection
我在嵌套集合中有选项时遇到了以下奇怪的问题:
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]])}}
我想这可能是一些类型擦除的问题,但这是 Scala 中的预期行为吗?有谁知道到底发生了什么?
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(_)} }
使用 Some(t): Option[Int]
而不是 Some(t).asInstanceOf[Option[Int]]
。它既短又安全:如果类型不匹配,它将无法编译。
我在嵌套集合中有选项时遇到了以下奇怪的问题:
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]])}}
我想这可能是一些类型擦除的问题,但这是 Scala 中的预期行为吗?有谁知道到底发生了什么?
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(_)} }
使用 Some(t): Option[Int]
而不是 Some(t).asInstanceOf[Option[Int]]
。它既短又安全:如果类型不匹配,它将无法编译。