Scala类型成员差异 [英] Scala type members variance
问题描述
请考虑以下简短代码段:
Consider this short snippet:
trait Table[+A] {
type RowType = Seq[A]
}
Scala 2.11.7编译器给出以下错误:
Scala 2.11.7 compiler gives the following error:
covariant type A occurs in invariant position in type Seq[A] of type RowType
为什么A
在Seq[A]
中处于不变位置,而Seq
本身被定义为trait Seq[+A]
?
Why is A
considered to be in invariant position in Seq[A]
while Seq
itself is defined as trait Seq[+A]
?
此外,如果我们忽略该错误,可以请您提供一个用例说明该类型定义的可能问题?
Also, could you please provide a use case demonstrating possible issues with this type definition if we ignore the error?
推荐答案
对于任何B <: A
,您的Table[B]#RowType
将比Table[A]#RowType
更具体.更具体的含义并不相同,因此编译器正在将类型别名的参数视为不变位置.
For any B <: A
your Table[B]#RowType
will be more concrete than Table[A]#RowType
. More concrete does not mean the same, so compiler is considering parameters for type aliases as invariant positions.
如何解决此问题.
您可以将类型定义为抽象,这意味着您应该稍后定义它,并且可能遇到相同的问题,但是在trait Table
级别上,这样的定义将是正确的
You can define your type as abstract, that mean you should define it later and probably stuck with same problem, but on trait Table
level such definition will be correct
trait Table[+A] {
type RowType <: Seq[A]
}
高等混凝土类型
您可以定义参数化类型成员,这可能会导致更改使用此类型的方式,但是在大多数情况下,应该可以完成这项工作.
Concrete higher-kinded type
You can define parameterized type member, which could lead to changing how you can use this type, but in most cases should do the job.
trait Table[+A] {
type RowType[+X] = Seq[X]
}
关于类型成员差异
不是我所擅长的领域,但我尝试描述自己的想法.
On type member variance
Not the strongest my field but i try to describe my thoughts.
假设您有
trait Table[+A] {
type RowType = Seq[A]
}
def mkTable[A]: Table[A] = new Table[A] {}
然后您关注
val tupleTable = mkTable[(String, String)]
val prodTable: Table[Product] = tupleTable
那么prodTable.RowType
是什么?
在您定义的情况下,应为Seq[Product]
.但是,等等,prodTable
和tupleTable
是同一对象,因此它们的成员应该相同,因此prodTable.RowType
应该是Seq[(String, String)]
In case of your definition it should be Seq[Product]
. But wait, prodTable
and tupleTable
are the same object, so their members should be the same, so prodTable.RowType
should be Seq[(String, String)]
但是如果您改用第一种方法
But if you change to the first approach like
trait Table[+A] {
type RowType <: Seq[A]
}
def mkTable[A]: Table[A] = new Table[A] {
type RowType = Seq[A]
}
编译器会知道Table[Product]
的RowType
是<: Seq[Product]
类型,对于Seq[(String, String)]
是正确的,并且所有歧义都消失了.
Compiler would know that RowType
for Table[Product]
is some type <: Seq[Product]
which is true for Seq[(String, String)]
and all ambiguilties are gone.
这篇关于Scala类型成员差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!