Yang
Yang

Reputation: 612

Scala order implicit conversions?

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

Answers (2)

Stephen
Stephen

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

Luka Jacobowitz
Luka Jacobowitz

Reputation: 23502

You can create an implicit Ordering for Tree if you want to compare Leafs and Nodes.

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

Related Questions