Section monoid_def.
Variable M : Set.
Record monoid : Set := mkmonoid
{u : M;
o : M -> M -> M;
point_assoc : forall a b c : M, o a (o b c) = o (o a b) c;
u_neutral_l : forall a : M, o u a = a;
u_neutral_r : forall a : M, o a u = a}.
Hint Resolve point_assoc u_neutral_r u_neutral_l: arith.
Variable MO : monoid.
Let u' := u MO.
Let o' := o MO.
Remark o'_assoc : forall a b c : M, o' a (o' b c) = o' (o' a b) c.
exact (point_assoc MO).
Qed.
Hint Resolve o'_assoc: arith.
Remark u'_neutral_l : forall a : M, o' u' a = a.
exact (u_neutral_l MO).
Qed.
Hint Resolve u'_neutral_l: arith.
Remark u'_neutral_r : forall a : M, o' a u' = a.
exact (u_neutral_r MO).
Qed.
Hint Resolve u'_neutral_r: arith.
(* powering ************)
Fixpoint power (x : M) (n : nat) {struct n} : M :=
match n with
| O => u'
| S n => o' x (power x n)
end.
(* some lemmas on powering *)
(***************************)
(******************************)
Hint Resolve power_u: arith.
(****************************************************)
Hint Resolve power_plus: arith.
(***********************************)

Lemma power_sym :
forall (a : M) (n p : nat),
o' (power a n) (power a p) = o' (power a p) (power a n).