Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering with algebraic types in scala

Tags:

scala

I have this:

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() = ...

}

I want to use

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

But it does not work:

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

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

How do I write this aglebraic type with different orderings for the individual constructors ?

like image 723
Bastl Avatar asked Dec 13 '25 16:12

Bastl


1 Answers

In Subtask you're not overriding the parent method correctly, because they take different parameter types. Try this:

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)
  }
  ...
}

However, when sorting, we need an Ordering[Issue], not an Ordering[Subtask], because the compare method takes an Issue.

So to sort a List[Subtype], for the compiler to get the correct Ordering object, it needs to be typed as a List[Issue] rather than List[Subtask].

So add a type annotation where you declare subtasks, or upcast it thus when calling:

(subtasks: List[Issue]).sorted
like image 59
Luigi Plinge Avatar answered Dec 16 '25 15:12

Luigi Plinge