更多 Scala 打字问题 [英] More Scala typing issues

查看:19
本文介绍了更多 Scala 打字问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

既然 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屋!

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