import algebra.group data.nat open expr decidable tactic nat meta_definition is_poly_bin_app : expr → option name | (app (app (app (app (const op ls) A) s) lhs) rhs) := some op | _ := none meta_definition is_add (e : expr) : bool := match is_poly_bin_app e with | some op := to_bool (op = `add) | none := ff end meta_definition flat_add (e : expr) : tactic (expr × expr) := do when (is_add e = ff) (fail "given expression is not an addition"), add_fn : expr ← return $ app_fn (app_fn e), A : expr ← return $ app_arg (app_fn add_fn), s : expr ← mk_app `add_semigroup [A] >>= mk_instance, assoc : expr ← mk_mapp `add.assoc [some A, some s], flat_assoc add_fn assoc e meta_definition tst_flat_add : tactic unit := do trace "--------", (lhs, rhs) ← target >>= match_eq, (new_lhs, H) ← flat_add lhs, trace H, exact H example (a b c d : nat) : a + b + c + d = a + (b + (c + d)) := by tst_flat_add example (a b c d : nat) : a + (b + (c + d)) = a + (b + (c + d)) := by tst_flat_add example (a b c d : nat) : ((a + b) + (c + d)) = a + (b + (c + d)) := by tst_flat_add example (a b c d e f : nat) : (a + b) + (c + (d + (e + f))) = a + (b + (c + (d + (e + f)))) := by tst_flat_add example (a b c d e f : nat) : (a + b + c) + (d + (e + f)) = a + (b + (c + (d + (e + f)))) := by tst_flat_add example (a b c d e f : nat) : a + b + c + d + e + f = a + (b + (c + (d + (e + f)))) := by tst_flat_add example (a b c d e f : nat) : a + (b + c) + (d + e) + f = a + (b + (c + (d + (e + f)))) := by tst_flat_add example (a b c d e f : nat) : a + (b + c + d) + (e + f) = a + (b + (c + (d + (e + f)))) := by tst_flat_add example (a b c d e f : nat) : a + (b + (c + d)) + (e + f) = a + (b + (c + (d + (e + f)))) := by tst_flat_add example (a b c d e f : nat) : (a + b) + (c + d) + (e + f) = a + (b + (c + (d + (e + f)))) := by tst_flat_add