Two related existential type parameters

48 Views Asked by At

Let's take this example code:

trait DataProcessor[D] {
  def computeData(): D   
}

case class DataItem[D, P <: DataProcessor[D]](processor: P, data: D)

def computeDataFromItems(items: Set[DataItem[_, _]]) = items collectFirst {
  case DataItem(s: DataProcessor[_], d) =>
    s.computeData()   
}

When compiled with Scala 2.11, it yield this error:

Error:(8, 77) type arguments [_$1,_$2] do not conform to class DataItem's type 
parameter bounds [D,P <: TwoExistentials.DataProcessor[D]]
  def computeDataFromItems(items: Set[DataItem[_, _]]) = items collectFirst {

It seems that the collectFirst method needs some more type information, that is not contained in the pair of existential types of the DataItem class.

Is there a chance to give more specific types to the method's arguments, something like:

def computeDataFromItems(items: Set[DataItem[D, P] forSome { type D, type P <: DataProcessor[D] }])

which unfortunately doesn't compile?

Otherwise, is there a way to allow for a class with two related type parameters to be used in collections, in a type-safe manner?

By the way, I have already considered using shapeless, instead of existential types. But I am looking for an implementation with classical Scala collections.

1

There are 1 best solutions below

0
Federico Pellegatta On BEST ANSWER

This should compile (replaced , with ;):

def computeDataFromItems(items: Set[DataItem[D, P] forSome { type D; type P <: DataProcessor[D] }])