here is my Problem:
I try to aggregate a List of Objects:
val list = List(Foo(1), Foo(2), Bar(2), Bar(3), Baz(5), Baz(3))
After the aggregation i want to have only one object for every aggregatable type in this list. In this Example Foo and Bar should be aggregatable where Baz isn't, so the result should be:
List(Foo(3), Bar(5), Baz(5), Baz(3))
My Idea was to define a trait Aggregatable as follows:
trait Aggregatable[T] {
def aggregate(agg: T): T
}
case class Foo(val x: Int) extends Aggregatable[Foo] {
def aggregate(agg: Foo) = {
val x = (0 /: List(this, agg))((old, elem) => (old + elem.x))
new Foo(x)
}
}
case class Bar(val x: Int) extends Aggregatable[Bar] {
def aggregate(agg: Bar) = {
val x = (0 /: List(this, agg))((old, elem) => (old + elem.x))
new Bar(x)
}
}
case class Baz(val x: Int)
Well, I think this is the obvious part of the Problem...
In the next step I try to aggregate the list. First I group the list into lists of homogenious types:
val grouped = list.groupBy( _.getClass().toString() )
/* => grouped should be
* Map(
* class Foo ->
* List(Foo(1), Foo(2)),
* class Bar ->
* List(Bar(3), Bar(4)),
* class Baz ->
* List(Baz(5), Baz(3))
* )
*/
Now for the sake of simplicity lets now assume that we want to find out if the first two elements of the first list are aggregatable:
val firstList = grouped.toList.apply(0)._2 // List(Foo(1), Foo(2))
val a = firstList (0) // Foo(1)
val b = firstList (1) // Foo(2)
This is where my actual problem begins. To determine if a and b can be aggregated, there must be a way to ask if a and b inherit from the same type Aggregatable[T] for some fixed T.
My way to ask this was to define a type aggregatablePair:
type aggregatablePair = Pair[T, T] forSome { type T <: Aggregatable[T] }
Build a pair out of a and b:
val pair = (a, b)
and aggregate them if they are an aggregatablePair:
pair match {
case aggPair: aggregatablePair => aggPair._1.aggregate(aggPair._2)
case _ => println("pair is not aggregatable")
}
but this doesn't work... the error is:
type mismatch;
found: aggPair._2.type (with underlying type T forSome { type T <: Aggregatable[T] })
required: T where type T <: Aggregatable[T]
In my opinion it sounds like the found type matches the required type... can anyone tell me why it dosn't? And what would be the right way to express what I want?
thank you for any help