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.
This should compile (replaced
,with;):