# Library UniMath.Tactics.Monoids_Tactics

Author: Michael A. Warren. Date: Spring 2015. Description: Some tactics for monoids.

Require Import UniMath.Algebra.Monoids.
Require Import UniMath.Tactics.Utilities.

Ltac op_strip f :=
repeat
match goal with
| |- f ?x ?y = f ?x ?z
apply (ap (λ v, f x v))
| |- f ?y ?x = f ?z ?x
apply (ap (λ v, f v x))
end.

Ltac assocop_clean M f :=
repeat rewrite <- (assocax M).

Ltac assocop_clean_in M f t :=
repeat rewrite <- (assocax M) in t.

Ltac assocop_clean_all M f :=
assocop_clean M f;
repeat
match goal with
| H : context[f ?x (f ?y ?z)] |- _assocop_clean_in M f H
end.

Ltac assocop_trivial M f :=
try (assocop_clean_all M f; op_strip f; apply idpath).

Ltac assocop_group_in M f x s t :=
let T := type of x in
match T with
| context[f s t] ⇒ idtac
| context [f (f ?u s) t] ⇒ rewrite (assocax M u s t) in x
| context [f s (f t ?u)] ⇒ rewrite <- (assocax M s t u) in x
end.

Ltac assocop_group M f s t :=
match goal with
| |- context [f s t] ⇒ idtac
| |- context [f (f ?u s) t] ⇒ rewrite (assocax M u s t)
| |- context [f s (f t ?u)] ⇒ rewrite <- (assocax M s t u)
end.

Ltac monoid_clean M :=
repeat rewrite (lunax M); repeat rewrite (runax M); assocop_clean M (@op M).

Ltac monoid_clean_in M t :=
repeat rewrite (lunax M) in t; repeat rewrite (runax M) in t;
assocop_clean_in M (@op M) t.

Ltac monoid_clean_all M :=
monoid_clean M;
repeat
match goal with
| H : _ |- _monoid_clean_in M H
end.

Ltac monoid_declean M :=
repeat rewrite (assocax M).

Ltac monoid_op_strip_left M :=
(monoid_declean M;
match goal with
| |- (@op M) ?x ?y = (@op M) ?x ?z
apply (ap (λ v, (@op M) x v))
| |- (?x × ?y = ?x × ?z)%multmonoidapply (ap (λ v, x × v))%multmonoid
end;
monoid_clean M).

Some error handling should be added (e.g., to check that lhs, rhs are of type M; that they are words in M, etc.).
Ltac monoid_zap_body M f :=
match goal with
| |- ?lhs = ?rhs
match lhs with
| rhsapply idpath
| (@unel M) ⇒ apply pathsinv0; monoid_zap_body M f
| _ ⇒ (monoid_op_strip_left M; monoid_zap_body M f)
end
| E : ?l = ?r |- ?lhs = ?rhsf E;
let g := make_hyp_check E in
let h := check_cons g f in
matched_rewrite E; monoid_zap_body M h
end.

Ltac monoid_zap M := monoid_clean_all M; monoid_zap_body M id_check.