2016-12-09 1 views
1

J'ai défini un type de données abstrait et je voulais le rendre assez général et évolutif. Cependant, le système de type scala me donne un cauchemar.Définition d'une méthode générique dans un trait lors de l'utilisation d'un type de données algébriques dans Scala

sealed trait Tree[+A] { 
    def evaluateTree(): A = this match { 
    case Leaf(value) => value 
    case Branch_A1(op, left) => op(evaluateTree(left)) 
    case Branch_A2(op, left, right) => op(evaluateTree(left),evaluateTree(right)) 
    } 
} 
case object EmptyTree extends Tree[Nothing] 
case class Leaf[A](value: A) extends Tree[A] 
case class Branch_A1[A](op: A => A, left: Tree[A]) extends Tree[A] 
case class Branch_A2[A](op: (A,A) => A, left: Tree[A], right: Tree[A]) extends Tree[A] 

Un serait par exemple Double. Donc, dans ce cas, j'ai un arbre qui a des branches qui représentent les fonctions de un et deux arguments (Branch_A1, Branch_A2)

Cependant, il ne compile pas. En op(evaluateTree(left)) il dit que "il ne peut pas résoudre ... avec une telle référence".

Je pourrais retirer la fonction de la classe dans un modèle plus fonctionnel mais je veux le faire après la conception d'un objet. La seule façon que je peux obtenir en faire la compilation est:

sealed trait Tree[+A] { 
    def evaluateTree(t: Tree[A]): A = this match { 
    case Leaf(value) => value 
    case Branch_A1(op, left) => op(evaluateTree(left)) 
    case Branch_A2(op, left, right) => op(evaluateTree(left),evaluateTree(right)) 
    } 
} 
case object EmptyTree extends Tree[Nothing] 
case class Leaf[A](value: A) extends Tree[A] 
case class Branch_A1[A](op: A => A, left: Tree[A]) extends Tree[A] 
case class Branch_A2[A](op: (A,A) => A, left: Tree[A], right: Tree[A]) extends Tree[A] 

ce qui est stupide car je dois passer l'instance de l'objet.

Je dois dire au compilateur que this est un Tree[A]. Donc j'ai essayé:

sealed trait Tree[+A] { 

    this: Tree[A] => 

    def evaluateTree(): A = this match { 
    case Leaf(value) => value 
    case Branch_A1(op, left) => op(evaluateTree(left)) 
    case Branch_A2(op, left, right) => op(evaluateTree(left),evaluateTree(right)) 
    } 
} 

Toujours le compilateur ne me laisse pas partir, l'erreur est la même chose. Comment puis-je résoudre ce problème?

+0

Eh bien, puisque vous voulez le faire en utilisant la conception d'objets, vous devez appeler des méthodes plutôt que des fonctions dans votre premier snipet: ' op (left.evaluateTree()) ' – Kolmar

Répondre

0

Il semble que vos récepteurs soient vissés. evaluateTree ne prend pas d'arguments. Je suppose que vous voulez évaluer la sous-arborescence, comme dans op(evaluateTree(left)) devrait plutôt être op(left.evaluateTree())

def evaluateTree(): A = this match { 
    case Leaf(value) => value 
    case Branch_A1(op, left) => op(left.evaluateTree()) 
    case Branch_A2(op, left, right) => op(left.evaluateTree(),right.evaluateTree()) 
} 
+0

vous avez absolument raison. Je dormais, système de type scala me donne tellement de mal que je ne vois même pas l'évidence. Je suppose que c'est un problème avec le système de types. –