2012-08-10 92 views
3

我有这样的:订货与代数类型斯卡拉

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类型与个人构造函数的不同顺序?

+0

使用'Ordering'代替。 – 2012-08-10 18:02:32

回答

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](...) 
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 
+0

你知道为什么编译器不会搜索typeclass实例的逆变类型吗? – sschaef 2012-08-10 15:35:29

+0

@sschaef不太确定你的意思。 '订购'是不变的;如果它是协变的,我们不会有这个问题,但也许这不是因为这里提到的问题:http://www.scala-lang.org/api/2.7.7/scala/Ordered.html – 2012-08-10 16:49:57

+0

是的,那是我搜索的是什么。 – sschaef 2012-08-10 17:29:31