2017-05-24 4 views
1

J'ai un problème dans l'ordre de scala implicite, quelqu'un peut-il m'aider? Ci-dessous quelques définitions de classes, et ce que je veux faire est de comparer Leaf et Node à travers sa 'popularité'.Scala commander des conversions implicites?

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 

pour exampel:

val a = Leaf("a",10) 
val b = Leaf("b",20) 
val c = Node(30,a,b) 

si l'on veut comparer a et b par sa popularité, il est facile de le faire en ajoutant les transformations implicites, comme:

implicit val leavesOrder = new Ordering[Leaf] { 
override def compare(x: Leaf, y: Leaf) = 
    implicitly[Ordering[Double]].compare(x.popularity, y.popularity) 
} 

mais si je veux comparer a et c à travers sa popularité, je suis confus à ce sujet et je ne sais pas comment ajouter les transformations implicites?

Quelqu'un peut-il m'aider?

+0

Votre question est un peu vague. Votre titre parle d'ordre implicite mais vous semblez rechercher des conversions implicites? –

+0

Vous pourriez créer un 'nouvel ordre [arbre]' –

+0

Désolé à ce sujet, je vais modifier la tuile. @ YuvalItzchakov – Yang

Répondre

1

Je fais quelque chose comme ça. Modifiez votre classe Tree en sealed trait cela signifie que la correspondance de modèle est exhaustive afin que le compilateur puisse vous indiquer si votre élément manquant. Ensuite, vous devez faire correspondre sur chacun des types qu'un arbre peut être. Ils n'ont pas tous une popularité.

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

} 
+0

Merci, j'essaie votre méthode. – Yang

+0

Bonjour, merci d'avance, lorsque j'essaie de tester votre code dans mon exemple, les messages suivants s'affichent: "Pas de commande implicite définie pour Leaf". Voici mon exemple: val a = Feuille ("a", 3) val b = Feuille ("b", 5) val e = Feuille ("e", 6) val c = Nœud (10, a, b) val d = Noeud (11, c, a) val s = Tableau (e, a, b) .sortie – Yang

+0

change 'val treeOrdering = ...' en implicit val treeOrdering = ...' – Stephen

2

Vous pouvez créer un Ordering implicite pour Tree si vous souhaitez comparer Leaf s et Node s.

est ici un code (incomplet), sur la façon dont vous pouvez le faire:

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 */ 
    } 
} 

points de bonus pour changer Tree être un sealed trait, de sorte que le compilateur peut vous dire quand votre correspondance de motif est incomplet :)

+0

Merci, je suis en train d'essayer votre code. – Yang

+0

Salut Luka, merci d'avance, quand j'essaie de tester votre code dans mon exemple, les messages suivants s'affichent, "Aucun ordre implicite défini pour Leaf". Voici mon exemple: val a = Feuille ("a", 3) val b = Feuille ("b", 5) val e = Feuille ("e", 6) val c = Node (10, a, b) val d = Noeud (11, c, a) val s = Tableau (e, a, b) .sortie – Yang

+0

Hmm, ça marche pour moi, pouvez-vous me montrer plus de votre code? –