I got this code from here: It's a very simple expression evaluation
sealed abstract class Tree
case class Add(t1: Tree, t2: Tree) extends Tree
case class Sub(t1: Tree, t2: Tree) extends Tree
case class Mul(t1: Tree, t2: Tree) extends Tree
case class Div(t1: Tree, t2: Tree) extends Tree
case class Num(t: Double) extends Tree
def eval(t: Tree): Double = t match {
case Add(t1, t2) => eval(t1)+eval(t2)
case Sub(t1, t2) => eval(t1)-eval(t2)
case Mul(t1, t2) => eval(t1)*eval(t2)
case Div(t1, t2) => eval(t1)/eval(t2)
case Num(t) => t
}
How can I decompose eval function into case classes (e.g. Add) so I can have something like: (How Scala compiler do this for Function*, I think these should have same answers)
sealed abstract class Tree{
def eval:???
}
case class Add(t1: Tree, t2: Tree) extends Tree{
def eval = ???
}
You could make the abstract Tree
class have an eval
method that returns a Double
:
sealed abstract class Tree {
def eval: Double
}
case class Add(t1: Tree, t2: Tree) extends Tree {
def eval = t1.eval + t2.eval
}
case class Sub(t1: Tree, t2: Tree) extends Tree {
def eval = t1.eval - t2.eval
}
case class Num(t: Double) extends Tree {
def eval = t
}
And then:
val tree = Add(Num(1), Sub(Num(2), Num(1))) //1+(2-1)
tree.eval //2.0
Another approach is to define a case class for each branching size of the tree:
sealed abstract class Tree {
def eval: Double
}
case class Tree2(func: (Double, Double) => Double)(d1: Tree, d2: Tree) extends Tree {
def eval = func(d1.eval, d2.eval)
}
case class Tree1(func: Double => Double)(d1: Tree) extends Tree {
def eval = func(d1.eval)
}
case class Tree0()(d1: Double) extends Tree {
def eval = d1
}
Then you can define new tree operations as vals
relatively ad-hoc, without defining new classes. This is sometimes preferable:
val Add = Tree2(_ + _) _
val Sub = Tree2(_ - _) _
val Num = Tree0() _
Of course, nothing here is special to Double
. You could make Tree
generic to parameterize the return type. Here's a small generic version, and an implementation with Strings
:
sealed abstract class Tree[T] {
def eval: T
}
case class Add(t1: Tree[String], t2: Tree[String]) extends Tree[String] {
def eval = t1.eval + t2.eval
}
case class Sub(t1: Tree[String], t2: Tree[String]) extends Tree[String] {
def eval = t1.eval.replaceAll(t2.eval, "")
}
case class Str(t: String) extends Tree[String] {
def eval = t
}
Add(Str("foo"), Sub(Str("barfoobarfoo"), Str("foo"))).eval //"foobarbar"
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments