2011-07-02 156 views
1

我有這樣的情況下類:簡化表達斯卡拉

abstract class Tree 

case class Sum(l: Tree, r: Tree) extends Tree 

case class Var(n: String) extends Tree 

case class Const(v: Int) extends Tree 

現在我寫這樣的對象:

object Main { 

    type Environment = String => Int 

    def derive(t: Tree, v: String): Tree = t match { 
    case Sum(l, r) => Sum(derive(l, v), derive(r, v)) 
    case Var(n) if (v == n) => Const(1) 
    case _ => Const(0) 
    } 

    def eval(t: Tree, env: Environment): Int = t match { 
    case Sum(l, r) => eval(l, env) + eval(r, env) 
    case Var(n) => env(n) 
    case Const(v) => v 
    } 

    def simple(t: Tree): Const = t match { 
    case Sum(l, r) if (l.isInstanceOf[Const] && r.isInstanceOf[Const]) => Const(l.asInstanceOf[Const].v + r.asInstanceOf[Const].v) 
    case Sum(l, r) if (l.isInstanceOf[Sum] && r.isInstanceOf[Sum]) => Const(simple(l).v+ simple(r).v) 
    case Sum(l, r) if (l.isInstanceOf[Sum]) => Const(simple(l).v + r.asInstanceOf[Const].v) 
    case Sum(l, r) if (r.isInstanceOf[Sum]) => Const(simple(r).v + l.asInstanceOf[Const].v) 
    } 

    def main(args: Array[String]) { 
    val exp: Tree = Sum(Sum(Var("x"), Var("x")), Sum(Const(7), Var("y"))) 
    val env: Environment = { 
     case "x" => 5 
     case "y" => 7 
    } 
    println("Expression: " + exp) 
    println("Evaluation with x=5, y=7: " + eval(exp, env)) 
    println("Derivative relative to x:\n " + derive(exp, "x")) 
    println("Derivative relative to y:\n " + derive(exp, "y")) 
    println("Simplified expression:\n" + simple(derive(exp, "x"))) 
    } 


} 

我在新階。是否可以使用少量代碼編寫方法simple,並且可能採用scala方式?

感謝您的諮詢。

回答

6

你快到了。在Scala中,提取可以嵌套:

def simple(t: Tree): Const = t match { 
    case Sum(Const(v1), Const(v2)) => Const(v1 + v2) 
    case Sum(s1 @ Sum(_,_), s2 @ Sum(_, _)) => Const(simple(s1).v+ simple(s2).v) 
    case Sum(s @ Sum(_, _), Const(v)) => Const(simple(s).v + v) 
    case Sum(Const(v), s @ Sum(_, _)) => Const(simple(s).v + v) 
} 

當然,這會給你不完全匹配的一些警告和SX @總和(_,_)一再表明,有可能是一個更好的辦法,其中包括匹配對Const和Var在根級別進行更多的遞歸調用。

+1

謝謝。 @是否像isInstanceOf一樣? –

+0

Kris會比我知道得更好,但我認爲它更像是「這種模式,我們將在@之後使用之前給出的名稱分配給val。」。 – pr1001

+2

@用於命名由模式匹配的值。 s @ Sum(_,_)與Sum的提取器匹配,並且如果成功則將s綁定到Sum。 –

0

只是一個小的改進:

def derive(t: Tree, v: String): Tree = t match { 
    case Sum(l, r) => Sum(derive(l, v), derive(r, v)) 
    case Var(`v`) => Const(1) 
    case _ => Const(0) 
} 
0

如何:

def simplify(t: Tree): Tree = t match { 
    case Sum(Const(v1),Const(v2)) => Const(v1+v2) 
    case Sum(left,right) => simplify(Sum(simplify(left),simplify(right))) 
    case _ => t //Not necessary, but for completeness 
} 

注意,它返回一個樹,而不是一個常量,所以它應該能夠使用變量來簡化樹了。

我學習Scala,因此任何建議,爲什麼這是行不通的等較受歡迎的:-)更


編輯:剛剛發現,第二種情況下使用時,會導致一個無限循環變量。使用替代它:

case Sum(left,right) => Sum(simplify(left),simplify(right)) 

很不幸,這打破時leftright返回常量,這可以進一步簡化(如Sum(Const(2),Const(3)))。

1

儘管這個問題已經關閉,但是我覺得這個版本應該是一個更好的,

def simplify(t: Tree): Tree = t match { 
    case Sum(Const(v1), Const(v2)) => Const(v1 + v2) 
    case Sum(Const(v1), Sum(Const(v2), rr)) => simplify(Sum(Const(v1 + v2), simplify(rr))) 
    case Sum(l, Const(v)) => simplify(Sum(Const(v), simplify(l))) 
    case Sum(l, Sum(Const(v), rr)) => simplify(Sum(Const(v), simplify(Sum(l, rr)))) 
    case Sum(Sum(ll, lr), r) => simplify(Sum(ll, simplify(Sum(lr, r)))) 
    case Sum(Var(n), r) => Sum(simplify(r), Var(n)) 
    case _ => t 
} 

似乎與變量「複雜」表達式的作品。