Черта Enumeratee неизменна в типе From при использовании ADT

Я пытаюсь составить Enumeratee.grouped и Enumeratee.filter, чтобы создать новый перечислитель, однако я столкнулся с проблемой дисперсии. Типы ввода и вывода моего перечисления - это ADT, и я получаю следующую ошибку.

<console>:24: error: type mismatch;
 found   : play.api.libs.iteratee.Enumeratee[OutputType,OutputType]
 required: play.api.libs.iteratee.Enumeratee[Product with Serializable with OutputType,OutputType]
Note: OutputType >: Product with Serializable with OutputType, but trait Enumeratee is invariant in type From.
You may wish to define From as -From instead. (SLS 4.5)

Я воссоздал свою проблему с меньшим примером здесь (я понимаю, что этот пример можно было бы переписать как Enumeratee.collect, однако, если нет способа объединить Enumeratee.grouped и Enumeratee.filter, это мне не поможет.)

import play.api.libs.iteratee.Enumeratee
import scala.concurrent.ExecutionContext.Implicits.global

sealed abstract class InputType
case class InputA(counter: Int) extends InputType
case object InputB extends InputType

sealed abstract class OutputType
case class OutputA(msg: String) extends OutputType
case object OutputB extends OutputType

val e: Enumeratee[InputType, OutputType] = Enumeratee.map[InputType] { 
  case InputA(counter) => OutputA(counter.toString)
  case InputB => OutputB
} compose Enumeratee.filter[OutputType] { 
  case OutputA("4") => false
  case _ => true
}

Я не могу переопределить тип From в Enumeratee на -From, как предполагает ошибка компилятора, потому что это игровая библиотека. Является ли ограничением библиотеки то, что вы не можете использовать ADT при составлении перечислений? Или есть лучший подход для этого варианта использования (поставить где-нибудь ClassTag, написать эту функциональность по-другому и т. д.)?


person Asa    schedule 19.08.2015    source источник


Ответы (1)


Я нашел решение, которое кажется нормальным. Если вы измените Enumeratee.map[InputType] на Enumeratee.map[InputType].apply[OutputType], модуль вывода получит инвариантный тип, и он отлично скомпилируется.

val e: Enumeratee[InputType, OutputType] = Enumeratee.map[InputType].apply[OutputType] { 
  case InputA(counter) => OutputA(counter.toString)
  case InputB => OutputB
}
person Asa    schedule 19.08.2015