Как использовать переменную с экзистенциальным типом, где требуется конкретный тип? - PullRequest
1 голос
/ 16 апреля 2019

Этот надуманный пример иллюстрирует суть моей проблемы:

trait Producer[X] {def make(): X }

sealed trait MyProducer[X] extends Producer[X]
case class MyProducerA(n: Int) extends MyProducer[Int] {...}
case class MyProducerB(s: String) extends MyProducer[String] {...}

def doWithProducer[P <: Producer[_]](producer: P): P = {
  makePair(producer) // the compiler fails to infer the type parameter
  producer
}

def makePair[X](p: Producer[X]): (X, X) = (p.make(), p.make())

// this is how I need to call the method
val myProducer: MyProducer[_] = ???
doWithProducer(myProducer)

Метод doWithProducer() не может иметь параметр типа для типа продукта, поскольку подтипы MyProducer имеют разные типы продуктов (или я уже ошибаюсь?). Внутри doWithProduct() я знаю, что у меня есть конкретный экземпляр Producer с параметром типа. Мне все равно, но он есть. Однако компилятор не может понять это.

Можно ли решить эту проблему без изменения сигнатур метода?

Обновление: Что я нахожу любопытным и что заставляет меня предположить, что должен быть способ, то, что я действительно могу косвенно зафиксировать тип продукта в переменной типа:

def duplicate[X](p: X): (X, X) = (p, p)

duplicate(producer.make)

Однако мне все еще не удается добраться до Producer[X].

1 Ответ

2 голосов
/ 16 апреля 2019

P <: Producer[_] означает, что P является производителем типа неизвестного . Вы не должны использовать экзистенциальный тип, если хотите сказать, что P является производителем некоторого известного типа, который будет выведен.

Попробуйте

def doWithProducer[X, P <: Producer[X]](producer: P): P = {
  makePair(producer)
  producer
}

или

def makePair(p: Producer[_]): (Any, Any) = (p.make(), p.make())

Вы должны изменить сигнатуру хотя бы одного из методов doWithProducer, makePair, чтобы они скомпилировались.

Или вы можете разыграть

def doWithProducer[P <: Producer[_]](producer: P): P = {
  makePair(producer.asInstanceOf[Producer[Any]]) 
  producer
}
...