在scala中使用代数类型进行排序

时间:2012-08-10 07:31:11

标签: scala

我有这个:

abstract class Issue( ... ) extends Ordered[Issue] { 
  def compare(o : Issue) = due.compare(o.due)
  def render() : String
}

case class Task( ..., subtasks : scala.List[Subtask]) extends Issue( ... ) {
  def render() = ...
}

case class Subtask( ..., parent : String ) extends Issue( ... ) {
  override def compare(o:Subtask) = {
    ... delegate to some field's compare function ...
  }

  def render() = ...

}

我想用

val l1 : List[Task] = tasks.sorted
val l2 : List[Subtask] = subtasks.sorted

但它不起作用:

error: diverging implicit expansion for type scala.math.Ordering[this.Subtask]

starting with method ordered in trait LowPriorityOrderingImplicits
         ,subtasks.sorted.map(_.render()).mkString(" | ")).mkString(" | ")

如何为各个构造函数编写具有不同排序的aglebraic类型?

2 个答案:

答案 0 :(得分:2)

Subtask中,您没有正确覆盖父方法,因为它们采用不同的参数类型。试试这个:

case class Subtask( ..., parent : String ) extends Issue( ... ) {
  override def compare(o: Issue) = o match {
    case x: Subtask => ... // your new comparison
    case x          => super.compare(x)
  }
  ...
}

但是,在排序时,我们需要Ordering[Issue],而不是Ordering[Subtask],因为compare方法需要Issue

因此,要对List[Subtype]进行排序,以便编译器获取正确的Ordering对象,需要将其键入为List[Issue]而不是List[Subtask]

因此,在声明subtasks时添加一个类型注释,或者在调用时添加一个类型注释:

(subtasks: List[Issue]).sorted

答案 1 :(得分:1)

您是否尝试将子类作为类型参数传递给抽象超类?像这样:

abstract class Issue[I <: Issue[I]](...) extends Ordered[I] {
  def compare(o: I) = due.compare(o.due)
}

case class Task(...) extends Issue[Task](...)

case class Subtask(...) extends Issue[Subtask](...)