从scala 中的类型层次结构树
- 设a:
Tuple2[Int,Int]
,我知道Tuple2[Int,Int]
是从Product2[Int,Int]
延伸而来的 - 设b:
1 *: 2 *: EmptyTuple
具有类型Tuple
(细化为Int *: Int *: EmptyTuple
)
它们是不同的类型,没有任何父关系。它们都只有Product
,它们都是从Product
扩展而来的。
但我可以将a
分配给b
,反之亦然,为什么?
在Scala 3中,Tuple1
。。。编译器对CCD_ 12类型进行了综合修改,扩展了CCD_。也就是说,Tuple2[A, B]
被修改为扩展A *: B *: EmptyTuple
(它扩展了Tuple
)。
因此,可以将Tuple2[Int, Int]
分配给Int *: Int *: EmptyTuple
。同样,相反的情况也是可能的,因为A *: ... EmptyTuple
将被视为TupleN
(<=22类型参数)。
它们是不同的类型,但这并不意味着它们不相关。1 *: 2 *: EmptyTuple
是Tuple2[Int,Int]
的亚型,因为单例文字1
和2
是Int
的亚型并且Tuple2
的类型参数是协变的。
可以将1 *: 2 *: EmptyTuple
的实例扩展为Tuple2[Int,Int]
,但不能反过来。
请注意,Tuple2[A, B]
和A *: B *: EmptyTuple
是等效的。基于问题的语法,假设1 *: 2 *: EmptyTuple
是类型级表达式,但如果它是值级表达式,则它的类型将是Int *: Int *: EmptyTuple
,相当于Tuple2[Int,Int]
。在这种情况下,两种类型的实例都是";可分配的";彼此之间。
参考代码:
@main def main() =
type T1 = Tuple2[Int, Int]
type T2 = 1 *: 2 *: EmptyTuple
val t1a: T1 = (1, 2) //compiles
val t2a: T2 = (1, 2) //compiles
val t1b: T1 = (2, 1) //compiles
// val t2b: T2 = (2, 1) // does not compile
// t1a: T2 //does not compile
t2a: T1 //compiles
summon[1 <:< Int] // compiles
// summon[1 =:= Int] // does not compile
summon[T2 <:< T1] //compiles
// summon[T1 <:< T2] // does not compile
// summon[T1 =:= T2] // does not compile
//these are the same types, not exclusively subtypes of one another
summon[Tuple2[Int, Int] =:= Int *: Int *: EmptyTuple]
summon[Tuple2[Int, Int] <:< Int *: Int *: EmptyTuple]
summon[Int *: Int *: EmptyTuple <:< Tuple2[Int, Int]]