更多 Scala 打字问题 [英] More Scala typing issues
问题描述
既然 Kim Stebel 帮助我理解如何用存在类型输入变量,我需要知道如何在继承中使用它们:
Now that Kim Stebel helped me understanding how to type variables with existential types, i need to know how to use them in inheritance:
以下代码无法编译:
class PagingListModel(startPageNumber: Int, pageSize: Int, query: Query[Projection[_ <: Product]]) extends AbstractListModel {
val itemStartNumber: Int = startPageNumber * pageSize
val items: List[Product] = getPageData()
override def getPageData(): List[Product] = {
db withSession {
return queryToQueryInvoker(query.drop(itemStartNumber).take(pageSize)).list
}
}
}
...出现错误:
no type parameters for method queryToQueryInvoker:
(q: org.scalaquery.ql.Query[org.scalaquery.ql.ColumnBase[T]])
org.scalaquery.ql.basic.BasicQueryInvoker[T]
exist so that it can be applied to arguments
(org.scalaquery.ql.Query[org.scalaquery.ql.Projection[_ <: Product]])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : org.scalaquery.ql.Query[org.scalaquery.ql.Projection[_ <: Product]]
required: org.scalaquery.ql.Query[org.scalaquery.ql.ColumnBase[?T]]
...这很奇怪,因为所需的类型确实在找到的类型的范围内...
…which is strange, because the required type is really inside the bounds of the found one…
PS:我真的只想对 getPageData()
返回的列表中的每个元组调用 foreach
......
PS: i really only want to be able to call foreach
on each Tuple in the list returned by getPageData()
…
推荐答案
我不认为这可以通过存在类型来完成.它与类型参数一起使用:
I don't think this can be done with an existential type. It works with a type parameter:
class PagingListModel[T <: Product](... query: Query[Projection[T]]) {
...
def getPageData(): List[_ <: Product] = ...
queryToQueryInvoker(query.drop(itemStartNumber).take(pageSize)).list
}
原始版本是正确的,但由于类似于 Haskell 的单态限制的限制,Scala 无法对其进行类型检查.queryToQueryInvoker 的类型参数必须是 Scala 不支持的通用类型 [T <: Product] forAll { type T }
.
The original version would be correct but Scala cannot typecheck it due to a limitation similar to Haskell's monomorphism restriction. The type parameter for queryToQueryInvoker would have to be a universal type [T <: Product] forAll { type T }
which is not supported by Scala.
通过使用显式类型参数,可以使用该特定类型实例化 queryToQueryInvoker.该方法仍然可以返回 List[_ <: Product]
因为 List 在其元素类型上是协变的.
By using an explicit type parameter, queryToQueryInvoker can be instantiated with that specific type. The method can still return List[_ <: Product]
because List is co-variant in its element type.
毕竟这是可能的.你必须将存在物移动到正确的位置:
It is possible after all. You have to move the existential to the right place:
class PagingListModel(... query: Query[Projection[T]] forSome { type T <: Product }) {
def getPageData(): List[_ <: Product] = ... {
val i = queryToQueryInvoker(query.drop(itemStartNumber).take(pageSize))
i.list
}
}
如果没有额外的变量 i
,编译器会推断出错误的类型,然后抱怨它.对我来说看起来像是一个错误.
Without the extra variable i
the compiler will infer the wrong type and then complain about it. Looks like a bug to me.
这篇关于更多 Scala 打字问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!