错误,高级类型 Scala:类型参数不符合。类型 T 的边界比类型 T 声明的边界更严格
Error, Higher Kinded types Scala: type arguments do not conform. type T's bounds are stricter than type T's declared bounds
下面是 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
是个问题?
是否有任何书籍或文章解释了此错误消息背后的原因?
也许在 Pierce 的 TAPL 书中的某处?
正如我在上面的评论中指出的那样,Test
的类型参数列表中的 TC
(以及错误消息中)不是您定义的 TC
前面几行——它是一个新的 类型构造函数参数 隐藏了特征 TC
.
(作为旁注,我强烈建议不要隐藏类型参数。在值级别隐藏变量可能会造成混淆,但隐藏类型参数几乎总是导致混淆的根源。)
类型构造函数参数在规范的第 4.4 节中讨论。来自该部分:
A type constructor parameter adds a nested type parameter clause to
the type parameter... The above scoping restrictions are generalized
to the case of nested type parameter clauses, which declare
higher-order type parameters. Higher-order type parameters (the type
parameters of a type parameter t) are only visible in their
immediately surrounding parameter clause (possibly including clauses
at a deeper nesting level) and in the bounds of 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
的类型参数比 Foo
中 X
的类型参数受到更严格的约束类型参数列表。如果您考虑一下,这是有道理的:当唯一适用于 MyIntOptionThingy
的 A
是 Some[Int]
、None.type
和 Option[Int]
?
为了完整起见,我引用了 SLS 的一些可能相关的部分:
关于 SLS 3.5.2 类型构造函数的一致性:
下面是 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
是个问题?
是否有任何书籍或文章解释了此错误消息背后的原因?
也许在 Pierce 的 TAPL 书中的某处?
正如我在上面的评论中指出的那样,Test
的类型参数列表中的 TC
(以及错误消息中)不是您定义的 TC
前面几行——它是一个新的 类型构造函数参数 隐藏了特征 TC
.
(作为旁注,我强烈建议不要隐藏类型参数。在值级别隐藏变量可能会造成混淆,但隐藏类型参数几乎总是导致混淆的根源。)
类型构造函数参数在规范的第 4.4 节中讨论。来自该部分:
A type constructor parameter adds a nested type parameter clause to the type parameter... The above scoping restrictions are generalized to the case of nested type parameter clauses, which declare higher-order type parameters. Higher-order type parameters (the type parameters of a type parameter t) are only visible in their immediately surrounding parameter clause (possibly including clauses at a deeper nesting level) and in the bounds of 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
的类型参数比 Foo
中 X
的类型参数受到更严格的约束类型参数列表。如果您考虑一下,这是有道理的:当唯一适用于 MyIntOptionThingy
的 A
是 Some[Int]
、None.type
和 Option[Int]
?
为了完整起见,我引用了 SLS 的一些可能相关的部分:
关于 SLS 3.5.2 类型构造函数的一致性: