在需要具体类型的情况下,如何使用存在类型的变量?

时间:2019-04-16 09:36:20

标签: scala types existential-type

这个人为的例子说明了我的问题的本质:

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 个答案:

答案 0 :(得分:2)

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())

您必须更改方法doWithProducermakePair中的至少一个的签名才能使其编译。

或者您可以投射

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