下面的代码可以编译
case class A(s:Int)
case class B(s:Int)
case class Box[T](t:T)
object DoublyNestedTypes extends App {
println("hello")
val l=List(Box(A(1)))
val l2=Box(A(2))::l
println(l2)
val l3=Box(B(1))::l2
println(l3)
}
并产生:
hello
List(Box(A(2)), Box(A(1)))
List(Box(B(1)), Box(A(2)), Box(A(1)))
有人可以解释一下这里发生了什么吗? 为什么编译不会失败?还是运行时执行?
我原以为这会失败,因为 l
的类型是 List[Box[A]]
而
Box(B(1))
的类型是 Box[B]
,那么我如何在 前面添加
?Box[B]
列表[框[A]]
现在 l3
的类型是什么?
这是否与类型删除有关?
在 Haskell 中,等效代码会在编译时失败吗? (我的感觉是会的。)
最佳答案
当具有 A
类型的值 a
和 B
类型元素的列表 l
时,a::l
不会失败,但会生成 List[C]
类型的列表,其中 C
是最小上限 类型 A
和 B
- 即它们最具体的通用父类(super class)型。如果类型 A
和 B
完全不相关,您只会得到一个 List[Any]
。这反射(reflect)在 ::
运算符的签名上(a::l
等同于 l.::(a)
):
sealed abstract class List[+A] {
def ::[B >: A] (x: B): List[B] = ...
}
你是对的,像这样的东西不会在 Haskell 中编译,那只是因为在 Haskell 中没有子类型这样的东西,所以最小上限的概念没有任何意义.
Scala这样做是好是坏,这是一个很有争议的问题。
关于scala - Scala 中的 A[B[C]] 类型,即嵌套类型构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22180610/