Я не могу понять эту декларацию Scala Generic - PullRequest
3 голосов
/ 08 августа 2011

Мне нужна помощь в обобщениях Scala.

У меня есть следующие "абстрактные" черты:

trait Base[B <: Base[B,M], M <: Meta[B,M]] {
    def meta: M
}
    // Manages instances of a general type
trait Meta[B <: Base[B,M], M <: Meta[B,M]] {
    // ...
}
    // Manages Metas of a general type
trait Manager[M <: Meta[_,M]] {
    def apply[N <: M](clazz: Class[N]): N
}

Затем я хочу определить более конкретную иерархию типов, например:

trait Thing[B <: Thing[B,M], M <: ThingMeta[B,M]] extends Base[B,M] {
    // ...
}
trait ThingMeta[B <: Thing[B,M], M <: ThingMeta[B,M]] extends Meta[B,M]{
    // ...
}
trait ThingManager extends *Manager[ThingMeta[_,_]]* {
    // ...
}

Последнее объявление дает мне эту ошибку:

type arguments [ThingMeta[_, _]] do not conform to trait Manager's type parameter bounds [M <: Meta[_, M]]

Как я могу сказать, что ThingManager является диспетчером для всех ThingMetas и поэтому сам по себе не принимает параметр типа.

Ответы [ 4 ]

2 голосов
/ 09 августа 2011

Вы ослабили объявление Manager, удалив здесь границу, но это слишком много:

trait Manager[M <: Meta[_,M]] {

Почему бы вам просто не избежать рекурсивного упоминания M?Со следующей строкой код, который вы предоставили, компилируется.

trait Manager[M <: Meta[_,_]] {

Это решение аналогично решению парадигмы, но я не вижу преимущества в использовании абстрактных типов.Единственное преимущество будет, если они позволят вам писать такие вещи, как:

type M = ThingMeta[_,M]

в ThingManager.

2 голосов
/ 08 августа 2011

Если вы скомпилируете это с -explaintypes, вы увидите это:

ThingMeta[_, _] <: Meta[_, ThingMeta[_, _]]?

Очевидно, это не так.Проблема в том, что Manager просто не дает вам никакой свободы выбора параметра второго типа M: он должен быть M сам - что приводит к рекурсииесли вы не определяете черту или класс.

Может быть, Майлз Сабин придумает способ сделать это - он часто удивляет меня путями обхода вещей, которые я считал невозможными - но, возможно, это было былучше использовать абстрактные типы вместо параметров типа или ослабить границы.

1 голос
/ 08 августа 2011

Решение более ограниченное, чем ваша работа:

trait Manager {
  type M <: Meta[_,_]
  def apply[N <: M](clazz: Class[N]): N
}

trait ThingManager extends Manager {
  type M = ThingMeta[_,_]
}
0 голосов
/ 08 августа 2011

А как насчет типов высокого порядка?

trait Manager[MetaType[B,M] <: Meta[B,M]] {
  def apply[N <: MetaType[_, _]](clazz: Class[N]): N
}

trait ThingManager extends Manager[ThingMeta]

Извините, у меня нет установки scala для проверки этого.

Редактировать . Получил одну установку скалы. Предыдущий код не компилируется (ограничения на параметры Meta в ограничении на MetaType не выполняются). Но этот код делает:

trait Manager[
    BaseType[B <: BaseType[B,M], M <: MetaType[B,M]] <: Base[B,M], 
    MetaType[B <: BaseType[B,M], M <: MetaType[B,M]] <: Meta[B,M]]  {
  def apply[N <: MetaType[_,_]](clazz: Class[N]): N
}

trait ThingManager extends Manager[Thing, ThingMeta] {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...