Ale*_*rov 8 scala variance higher-kinded-types
考虑这个简短的片段:
trait Table[+A] {
type RowType = Seq[A]
}
Run Code Online (Sandbox Code Playgroud)
Scala 2.11.7编译器给出以下错误:
covariant type A occurs in invariant position in type Seq[A] of type RowType
Run Code Online (Sandbox Code Playgroud)
为什么被A认为处于不变的位置,Seq[A]而Seq它本身被定义为trait Seq[+A]?
另外,如果我们忽略错误,您能否提供一个用例来说明此类型定义可能存在的问题?
Odo*_*ois 10
对于任何B <: A你Table[B]#RowType将更具体的Table[A]#RowType.更具体并不意味着相同,因此编译器将类型别名的参数视为不变位置.
你怎么能解决这个问题.
您可以将类型定义为抽象,这意味着您应该稍后定义它并且可能会遇到相同的问题,但是在trait Table级别上这样的定义将是正确的
trait Table[+A] {
type RowType <: Seq[A]
}
Run Code Online (Sandbox Code Playgroud)
您可以定义参数化类型成员,这可能会导致更改您使用此类型的方式,但在大多数情况下应该完成这项工作.
trait Table[+A] {
type RowType[+X] = Seq[X]
}
Run Code Online (Sandbox Code Playgroud)
不是我最强的领域,但我试着描述我的想法.
假设你有
trait Table[+A] {
type RowType = Seq[A]
}
def mkTable[A]: Table[A] = new Table[A] {}
Run Code Online (Sandbox Code Playgroud)
然后你做了以下
val tupleTable = mkTable[(String, String)]
val prodTable: Table[Product] = tupleTable
Run Code Online (Sandbox Code Playgroud)
那会是prodTable.RowType什么?
如果你的定义应该是Seq[Product].但是等等,prodTable并且tupleTable是同一个对象,所以他们的成员应该是相同的,所以prodTable.RowType应该是Seq[(String, String)]
但是如果你改成第一种方法就好了
trait Table[+A] {
type RowType <: Seq[A]
}
def mkTable[A]: Table[A] = new Table[A] {
type RowType = Seq[A]
}
Run Code Online (Sandbox Code Playgroud)
编译器会知道RowType的Table[Product]是某种类型的<: Seq[Product]这是真的Seq[(String, String)],所有ambiguilties都不见了.
| 归档时间: |
|
| 查看次数: |
354 次 |
| 最近记录: |