Scala类型成员差异 [英] Scala type members variance

查看:76
本文介绍了Scala类型成员差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下简短代码段:

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

为什么ASeq[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].但是,等等,prodTabletupleTable是同一对象,因此它们的成员应该相同,因此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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆