Reputation: 612
I have some problem in scala order implicit, can someone help me?
Below are some classes definition, and what I want to do is to compare Leaf and Node through it's 'popularity'.
class Tree
case class EmptyTree() extends Tree
case class Leaf(label: String, popularity: Double) extends Tree
case class Node(popularity: Double, left: Tree, right: Tree) extends Tree
for exampel:
val a = Leaf("a",10)
val b = Leaf("b",20)
val c = Node(30,a,b)
if we want to compare a and b through it's popularity, it is easy to do by adding the implicit transformations, like that:
implicit val leavesOrder = new Ordering[Leaf] {
override def compare(x: Leaf, y: Leaf) =
implicitly[Ordering[Double]].compare(x.popularity, y.popularity)
}
but if I want to compare a and c through it's popularity, I am confused about it and don't konw how to add the implicit transformations?
Can someone help me?
Upvotes: 1
Views: 146
Reputation: 4296
Id do something like this. Change your Tree
class to a sealed trait
this means the pattern matching is exhaustive so the compiler can tell you if your missing something. Then you need to match on each of the types that a Tree can be. Not all of them have a popularity.
sealed trait Tree
case object EmptyTree extends Tree
case class Leaf(label: String, popularity: Double) extends Tree
case class Node(popularity: Double, left: Tree, right: Tree) extends Tree
implicit val treeOrdering = new Ordering[Tree] {
private val doubleOrdering = implicitly[Ordering[Double]]
def compare(a: Tree, b: Tree): Int = {
(a, b) match {
case (Node(p1, _, _), Node(p2, _, _)) => doubleOrdering.compare(p1, p2)
case (Leaf(_, p1), Node(p2, _, _)) => doubleOrdering.compare(p1, p2)
case (Node(p1, _, _), Leaf(_, p2)) => doubleOrdering.compare(p1, p2)
case (Leaf(_, p1), Leaf(_, p2)) => doubleOrdering.compare(p1, p2)
case (EmptyTree, _) => -1
case (_, EmptyTree) => 1
}
}
}
Upvotes: 1
Reputation: 23502
You can create an implicit Ordering
for Tree
if you want to compare Leaf
s and Node
s.
Here's some (incomplete) code, on how you could do that:
implicit val treeOrder = new Ordering[Tree] {
override def compare(x: Tree, y: Tree) = (x,y) match {
case (Leaf(_,xP), Leaf(_,yP)) => xP compare yP
case (Node(xP,_,_), Leaf(_,yP)) => xP compare yP
case (Node(xP,_,_), Node(yP,_,_)) => xP compare yP
case (EmptyTree(), _) => -1
/* Add the rest of the cases here */
}
}
Bonus points for changing Tree
to be a sealed trait
, so that the compiler can tell you when your pattern matching is incomplete :)
Upvotes: 2