views:

124

answers:

2

I want the expression (x-x) to be simplified to 0.

type aexpr = 
| CstI of int
| Var of string
| Add of aexpr * aexpr
| Sub of aexpr * aexpr
| Mul of aexpr * aexpr;;

let rec simplify expr =
match expr with
| Add(CstI(n1), CstI(n2)) ->CstI(n1 + n2)
| Sub(CstI(n1), CstI(n2)) ->CstI(n1 - n2)
| Mul(CstI(n1), CstI(n2)) ->CstI(n1 * n2)
| Add(e, CstI(0)) -> simplify e
| Add(CstI(0), e) -> simplify e
| Sub(CstI(0), e) -> simplify e
| Sub(e, CstI(0)) -> simplify e
| Sub(Var(x1), Var(x2)) when x1.Equals(x2) -> CstI(0) // <- not working
| Mul(CstI(0), e) -> CstI(0)
| Mul(e, CstI(0)) -> CstI(0)
| Mul(CstI(1), e) -> simplify e
| Mul(e, CstI(1)) -> simplify e
| _ -> expr;;

This does not do it. I do not see what I am doing wrong. Hope you can help me :)

Edit: It compiles fine but it does not do anything. Ie.

let e = Mul(CstI(1), Add(CstI(4), Sub(Var("x"), Var("x"))));;

In f# interactive:

let result = simplify e;;
val result : aexpr = Add (CstI 4,Sub (Var "x",Var "x"))

Result should be CstI 4

A: 

It seems to work here. You're not dealing with a case-sensitivity issue with the string comparison, are you?

Daniel Pratt
See updated question.
bobjink
+6  A: 

simplify (Sub (Var "x", Var "x")) works just fine. The reason that your example does not work is that simplify does not traverse the whole tree, so the Sub (Var "x", Var "x") part of the tree is never simplified.

In short, you're missing a case Sub (e,e) -> Sub (simplify e, simplify e) and the same for the other operators.

sepp2k
Note that even with this change, you might need to run multiple passes to get a fully simplified result. E.g. you ultimately would like to reduce `Sub(CstI 5, Add(CstI 1, CstI 2))` not just to `Sub(CstI 5, CstI 3)`, but all the way to `CstI 2`.
kvb
Good catch! Thanks!
bobjink