以下是Scala REPL中的一个简单实验:
scala> trait A; trait B extends A; trait C extends B
defined trait A
defined trait B
defined trait C
scala> trait TC[T]
defined trait TC
scala> trait TC2[T <: B]
defined trait TC2
scala> class Test[TC[T]]
warning: there was one feature warning; re-run with -feature for details
defined class Test
scala> new Test[TC]
res1: Test[TC] = Test@6f195bc3
scala> new Test[TC2]
<console>:11: error: kinds of the type arguments (TC2) do not conform to the expected kinds of the type parameters (type TC) in class Test.
TC2's type parameters do not match type TC's expected parameters:
type T (in trait TC2)'s bounds <: B are stricter than type T's declared bounds >: Nothing <: Any
val res2 =
^
<console>:12: error: kinds of the type arguments (TC2) do not conform to the expected kinds of the type parameters (type TC) in class Test.
TC2's type parameters do not match type TC's expected parameters:
type T (in trait TC2)'s bounds <: B are stricter than type T's declared bounds >: Nothing <: Any
new Test[TC2]
^
问题1:
如何根据Scala语言规范解释这些错误消息?
换句话说,SLS的哪些部分解释了这些错误消息?
问题2:,如何用简单术语解释这些错误消息(不是基于SLS)?
用编译器的话来描述上一个问题:
为什么这是TC2's type parameters do not match type TC's expected parameters
的问题,即type T (in trait TC2)'s bounds <: B are stricter than type T's declared bounds >: Nothing
?
是否有任何书籍或文章解释了此错误消息背后的原因?
也许在皮尔斯的TAPL书中某处?
答案 0 :(得分:7)
正如我在上面的评论中所述,TC
的类型参数列表中的Test
(以及错误消息中)不是您定义了几行的TC
早期 - 它是一个新的类型构造函数参数,它会影响特征TC
。
(作为旁注,我强烈建议不要使用阴影类型参数。值级别的阴影变量可能会让人感到困惑,但阴影类型参数几乎总是混淆的。)
类型构造函数参数在规范的4.4节中讨论。从那一节:
类型构造函数参数将嵌套的类型参数子句添加到 类型参数...上面的范围限制是一般化的 对于嵌套类型参数子句的情况,声明 高阶类型参数。高阶类型参数(类型 类型参数 t )的参数仅在其中可见 紧邻周围的参数子句(可能包括子句) 在更深的嵌套级别)和 t 的范围内。
您的T
这是其中一个高阶类型参数。它可以是有界的(像任何其他类型参数一样),但它不是。这就是导致错误的原因:您尝试提供一个类型构造函数,将其类型参数(TC2
)约束为不共享约束的类型构造函数参数的值(在事实上根本没有任何限制。
要直观地了解这是一个问题,请考虑以下特征:
trait Foo[X[_]] {
def create[A]: X[A]
}
这是一个非常合理的事情 - 我可以像这样创建一个实例:
object ListFoo extends Foo[List] {
def create[A]: List[A] = Nil
}
现在假设我有一个带约束的类型构造函数:
trait MyIntOptionThingy[A <: Option[Int]]
编译器禁止我实例化Foo[MyIntOptionThingy]
,因为MyIntOptionThingy
的类型参数的约束比X
中Foo
的类型参数更严格。 s类型参数列表。如果您考虑这一点,这是有道理的:当create
唯一适用于A
的{{1}} A
时,我将如何为MyIntOptionThingy
定义Some[Int]
None.type
1}},Option[Int]
和{{1}}?
答案 1 :(得分:0)
为了完整起见,我引用了一些可能与SLS相关的部分:
关于SLS 3.5.2中类型构造函数的一致性: