我正在阅读Scala规范中的本地类型推断部分(第6.26.4节),更具体地说是示例6.26.3。
例如,有以下函数和定义的值:
def cons[A](x: A, xs: List[A]): List[A] = x :: xs
def nil[B]: List[B] = Nil
val xs = cons(1, nil)
其中xs
被推断为List[Int]
类型。到现在为止还挺好。
然后,该示例使用以下值:
val ys = cons("abc", xs)
反过来推断它是List[Any]
类型,这完全有道理。对我来说没有多大意义的是它的推理。它说第二个参数是用预期的类型List[a]
键入的(为什么突然小写字母btw。?),据说失败,因为List[Int]
(xs
的类型)是不是List[a]
的子类型。因此,他们将其键入List[undefined]
重试,然后成功。但是,第一个参数输入为String
,没有问题,尽管它的预期类型是a
(或A
?)。
此外,第二种策略只能通过在类型中用undefined
替换类型参数,而不是用undefined
替换类型本身(或者暗示某种方式?)。
现在问题是,a
是一个类型常量,为什么String
(显然)是a
的子类型,而List[Int]
不是{{1}的子类型即使List[a]
是协变的,也是如此?
答案 0 :(得分:2)
作为类型常量的小写a
并将类型参数作为未定义(当使用pt失败时)都出现在第3段中“case 3:methods”的末尾。
您不能说List[Int] <:< List[a]
因为a
可能会变成String
,例如。
自Int <:< undefined
起,您将xs
的类型设为List[Int]
。这很好,因为你想要与其他arg类型的最小上限。 (想象一下,另一个arg是一个有趣的列表,a
竟然是Foo
。这些例子通常涉及动物:狗和猫成为宠物,或其他什么。)
在该步骤中,您真正询问a
是什么,因此a?
。然后,最好是String <: a?
。它只选择String
,因为它不是参数化类型。
当然,这只是非专家的措辞。