вот моя проблема:
Я пытаюсь собрать список объектов:
val list = List(Foo(1), Foo(2), Bar(2), Bar(3), Baz(5), Baz(3))
После агрегирования я хочу иметь только один объект для каждого агрегируемого типа в этом списке. В этом примере Foo и Bar должны быть агрегируемыми, а Baz - нет, поэтому результат должен быть:
List(Foo(3), Bar(5), Baz(5), Baz(3))
Моя идея состояла в том, чтобы определить черту Агрегируемый следующим образом:
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)
Ну, я думаю, что это очевидная часть проблемы ...
На следующем шаге я пытаюсь объединить список. Сначала я группирую список в списки однородных типов:
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))
* )
*/
Теперь, ради простоты, давайте теперь предположим, что мы хотим выяснить, можно ли агрегировать первые два элемента первого списка:
val firstList = grouped.toList.apply(0)._2 // List(Foo(1), Foo(2))
val a = firstList (0) // Foo(1)
val b = firstList (1) // Foo(2)
Вот тут и начинается моя настоящая проблема. Чтобы определить, могут ли агрегироваться a и b, должен быть способ узнать, наследуются ли a и b от одного и того же типа Aggregatable [T] для некоторого фиксированного T.
Мой способ задать этот вопрос - определить тип aggregatablePair:
type aggregatablePair = Pair[T, T] forSome { type T <: Aggregatable[T] }
Создайте пару из a и b:
val pair = (a, b)
и агрегируйте их, если они являются объединяемой парой:
pair match {
case aggPair: aggregatablePair => aggPair._1.aggregate(aggPair._2)
case _ => println("pair is not aggregatable")
}
но это не работает ... ошибка:
type mismatch;
found: aggPair._2.type (with underlying type T forSome { type T <: Aggregatable[T] })
required: T where type T <: Aggregatable[T]
На мой взгляд, похоже, что найденный тип соответствует требуемому типу ... Кто-нибудь может сказать мне, почему это не так?
И какой будет правильный способ выразить то, что я хочу?
спасибо за любую помощь