以下代码编译
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]
添加到List[Box[A]]
?
现在l3
的类型是什么?
这是否必须对类型擦除做些什么?
Haskell中编译时等效代码是否会失败? (我的感觉就是它。)
答案 0 :(得分:7)
当a
类型的值A
和l
类型的元素列表B
时,a :: l
不会失败,但会产生一个列表键入List[C]
,其中C
是类型A
和B
的最低上限 - 也就是说,它们是最具体的常见超类型。如果类型A
和B
完全不相关,那么您只需获得List[Any]
。这由::
运算符(a :: l
等同于l.::(a)
)的签名反映出来:
sealed abstract class List[+A] {
def ::[B >: A] (x: B): List[B] = ...
}
你是对的,这样的东西不能在Haskell中编译,这只是因为在Haskell中没有子类型这样的东西,所以最小上界的概念没有任何意义
Scala这样做是好还是坏是一个非常有争议的问题。