Типирование скалы требует неявного

Я пытаюсь построить следующее

У меня есть родительский родовой класс

abstract class ResultProvider[+T: Writes](db: DB) {
  def get(id: Long): Future[Seq[T]]
}

И некоторые реализации, например

class LengthProvider(db: DB) extends ResultProvider[LengthResult](db){
  override def get (userId: Long): Future[Seq[LengthResult]] = ...
}

object LengthProvider extends ((DB) => DisciplinePredictor) {
  override def apply(db: DB) = new LengthProvider(db)
}

У меня есть следующая карта конфигурации:

val providers: Map[String, ((DB) => ResultProvider[???])] = Map(
  "length" -> LengthProvider,
  "width"  -> WidthProvider,
   ...
)

Мой вопрос, что я должен поставить вместо???. В идеале это должно быть что-то вроде T : Writes, как я только забочусь, что этот тип имеет Writes имплицитно реализовано, так как я собираюсь Json.toJson Это. Это будет компилироваться с Any, но тогда информация, которую должен реализовать класс Writes неявное потеряно. Или я должен использовать другой подход? Я мог бы, вероятно, создать суперкласс для всех моих классов прецедентов (например,LengthResult), но я хочу сойти с рук.

1 ответ

Решение

Вы должны быть в состоянии написать ResultProvider[_] (ищите "экзистенциальные типы", если вы не знакомы с этим синтаксисом), но вам нужно дать имя неявному:

abstract class ResultProvider[+T](db: DB)(implicit val writes: Writes[T]) { ... }

В другом месте:

val provider: ResultProvider[_] = providers("length")
import provider.writes // makes the implicit visible here
...

Возможно, вам придется помочь компилятору (или вам самим, если вам нужно назвать тип), предоставив переменную типа:

providers("length") match {
  case provider: ResultProvider[a] =>
    import provider.writes 
    ...
}
Другие вопросы по тегам