2011-07-02 3 views
1

で式を簡素化私は、このようなケースクラスている:はScalaの

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


} 

私はScalaで新しいです。それはコードの小さなカウントとおそらくスカラーの方法でsimpleの書き込みメソッドが可能ですか?

ありがとうございました。

答えて

6

あなたはほぼあります。

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 @合計(_、_)を繰り返しマッチングを含んでより良い方法があるかもしれないことを示唆している:スカラ座では、抽出は、入れ子にすることができますon ConstとVarをルートレベルで使用し、より再帰的な呼び出しをシンプルにします。

+1

ありがとうございました。 @はisInstanceOfのようなものですか? –

+0

クリスは私よりよく知っているだろうが、私はそれが "@の後に与えられた名前を使用して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 
} 

注それは木、ないのConstを返すので、あまりにも変数で木を簡素化することができるはず。

私はこれがなどを動作しない理由として任意の提案は大歓迎:-)


EDIT以上あるので、Scalaのを学んでいる:ちょうど使用したときに、第2のケースは、無限ループを引き起こすことを発見しました変数。でそれを置き換えます

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

することは残念ながら、これは壊れた場合でも、さらに簡単にすることができleftrightリターンのConst、(例えば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 
} 

それは変数と「複雑な」表現で作品を思わ。