Компилятор Scala не может вывести смесь- в типе для сопоставления с образцом

У меня есть вариант использования для алгебраических групп над конечными наборами перестановок. Поскольку я хотел бы использовать группу для различных классов перестановок, которые в противном случае не связаны, я хотел бы сделать это в качестве дополнительной черты. Вот отрывок из моих попытка

trait Permutation[P <: Permutation[P]] { this: P =>
  def +(that: P): P

  //final override def equals(that: Any) = ...
  //final override lazy val hashCode = ...

  // Lots of other stuff
}

object Permutation {
  trait Sum[P <: Permutation[P]] extends Permutation[P] { this: P =>
    val perm1, perm2: P

    // Lots of other stuff
  }

  private object Sum {
    def unapply[P <: Permutation[P]](s: Sum[P]): Some[(P, P)] = Some(s.perm1, s.perm2)
    //def unapply(s: Sum[_ <: Permutation[_]]): Some[(Permutation[_], Permutation[_])] = Some(s.perm1, s.perm2)
  }

  private def simplify[P <: Permutation[P]](p: P): P = {
    p match {
      case Sum(a, Sum(b, c)) => simplify(simplify(a + b) + c)

      // Lots of other rules

      case _ => p
    }
  }
}

В какой-то момент я хотел бы вызвать метод упрощения, чтобы, ну, упростить выражение групповых операций с использованием алгебраических аксиом. Использование сопоставления с образцом кажется разумным, поскольку существует необходимо оценить множество аксиом, а синтаксис лаконичен. Однако, если я компилирую код, я получаю:

error: inferred type arguments [P] do not conform to method unapply's type parameter bounds [P <: Permutation[P]]

Я не понимаю, почему компилятор не может правильно определить тип, и я не знаю, как ему помочь. Фактически, тип параметра P не имеет значения при сопоставлении с образцом в этом случае. Если p - любая сумма перестановок, шаблон должен совпадать. Тип возвращаемого значения по-прежнему P, потому что преобразование выполняется исключительно путем вызова оператора + на P.

Итак, во второй попытке я заменяю закомментированную версию unapply. Однако затем я получаю сообщение об ошибке от компилятора (2.8.2):

assertion failed: Sum((a @ _), (b @ _)) ==> Permutation.Sum.unapply(<unapply-selector>) <unapply> ((a @ _), (b @ _)), pt = Permutation[?>: Nothing <: Any]

Есть какие-нибудь подсказки, как заставить компилятор принять это?

Заранее спасибо!

7
задан Christian Schlichtherle 10 October 2011 в 11:17
поделиться