Scala类,在可导出类型的参数中具有协方差

时间:2014-07-21 20:06:50

标签: scala generics types covariance

我想要这个类型类:

abstract class Model[U](val query: TableQuery[ModelTable[U]]) {
    // ...
}

但是在查询类型中有协方差。

我的想法是我有一个带U实例的函数,需要访问相应TableQuery [ModelTable [U]]的实例。 添加一个类型参数很讨厌,因为我不能再使用上下文边界来编写函数了:

def f[U : Mode](u: U) = // ...

每次都写出隐含的参数是非常麻烦的。 至于现在,我不明白为什么这是不可能的。给定U的具体类型,查询的类型约束对于编译器来说应该是微不足道的。

也许更具体:为什么不能编译:

// error: Unbound Wildcard Type
abstract class Model[U](val query: _ <: TableQuery[ModelTable[U]]) {
    // ...
}

1 个答案:

答案 0 :(得分:0)

query参数已经是协变的。看来你有这样的问题:

class TableQuery[T]
class TableQuerySub[T] extends TableQuery[T]
class ModelTable[T]
class ModelTableSub[T] extends ModelTable[T]

class Model[U](val query: TableQuery[ModelTable[U]])

val x1: TableQuerySub[ModelTable[Int]] = ???
val x2: TableQuery[ModelTableSub[Int]] = ???
new Model(x1)
new Model(x2) // does not compile

此处x2无法使用以下消息进行编译:

type mismatch;
found : TableQuery[ModelTableSub[Int]]
required: TableQuery[ModelTable[?]] 
Note: ModelTableSub[Int] <: ModelTable[?], 
but class TableQuery is invariant in type T. 
You may wish to define T as +T instead. (SLS 4.5)

此处编译器告诉我们,它不确定TableQuery[ModelTableSub[_]]是否扩展TableQuery[ModelTable[_]]。为了告诉编译器这实际上是这种情况,我们需要创建TableQuery协变的参数

class TableQuery[+T]

如果这对您没有帮助,请在您的问题中加入用例。


修改

添加第二个类型参数仍允许您指定上下文绑定。上下文绑定语法只不过是语法糖。以下陈述是相同的:

def f[U : Model](u:U) = {
  val m = implicitly[Model[U]]
  ???
}
def f[U](u:U)(implicit m:Model[U]) = ???

有了这些知识,我们可以为具有多个参数的上下文添加上下文绑定:

class Model2[A, B]

def f[U](u:U)(implicit m:Model[_, U]) = ???

如果你真的想用上下文绑定语法来指定它,你可以这样做

type AnyModel2[B] = Model2[_, B]
def f[U : AnyModel2](u:U) = ???

没有类型别名,你会得到(在我看来不太可读)

def f[U : ({type T[x] = Model2[_, x]})#T](u:U) = ???