inductive Expr | Val : Int → Expr | Var : String → Expr | Add : Expr → Expr → Expr | Mul : Expr → Expr → Expr open Expr def Expr.toString : Expr → String | (Val n) := toString n | (Var x) := x | (Add f g) := "(" ++ Expr.toString f ++ " + " ++ Expr.toString g ++ ")" | (Mul f g) := "(" ++ Expr.toString f ++ " * " ++ Expr.toString g ++ ")" instance : HasToString Expr := ⟨Expr.toString⟩ partial def addAux : Expr → Expr → Expr | f (Add (Val n) g) := addAux (Val n) (addAux f g) | f g := Add f g def add (a b : Expr) : Expr := addAux a b def main (xs : List String) : IO UInt32 := do let x := Var "x", IO.println (add (Val 1) (Add (Mul (Val 2) x) x)), pure 0