Больше проблем при наборе Scala - PullRequest
2 голосов
/ 26 мая 2011

Теперь, когда Ким Стебель помог мне понять , как печатать переменные с экзистенциальными типами, мне нужно знать, как использовать их в наследовании:

следующий код не компилируется:

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]]

…, что странно, поскольку требуемый тип действительно находится в границах найденного…

PS: iна самом деле нужно только иметь возможность вызывать foreach для каждого кортежа в списке, возвращаемого getPageData()

Ответы [ 2 ]

2 голосов
/ 28 мая 2011

Я не думаю, что это можно сделать с экзистенциальным типом. Работает с параметром типа:

class PagingListModel[T <: Product](... query: Query[Projection[T]]) {
  ...
  def getPageData(): List[_ <: Product] = ...
    queryToQueryInvoker(query.drop(itemStartNumber).take(pageSize)).list
}

Исходная версия была бы правильной, но Scala не может проверить ее из-за ограничения, подобного ограничению мономорфизма Хаскелла. Параметр типа для queryToQueryInvoker должен быть универсальным типом [T <: Product] forAll { type T }, который не поддерживается Scala.

Используя явный параметр типа, можно создать экземпляр queryToQueryInvoker с этим конкретным типом. Метод по-прежнему может возвращать List[_ <: Product], поскольку List является ко-вариантом в своем типе элемента.

Редактировать: Это все-таки возможно. Вы должны переместить экзистенциальное в нужное место:

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 компилятор выведет неверный тип, а затем пожалуется на него. Выглядит как ошибка для меня.

1 голос
/ 28 мая 2011

Мои знания ScalaQuery ограничены, но похоже, что вы должны параметризовать класс.

class PagingListModel[T <: Product] (
  startPageNumber: Int,
  pageSize: Int,
  query: Query[Projection[T]]
) extends AbstractListModel {
  ...
}

Существующие могут быть хитрыми, и их лучше избегать, если это вообще возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...