(* Contribution to the Coq Library   V6.3 (July 1999)                    *)
(*Recursive Definition addZ : Z -> Z -> Z := OZ   y => y | (pos O)   y => (succZ y) | (pos (S n1))   y => (succZ (addZ (pos n1) y)) | (neg O)   y => (predZ y) | (neg (S n1))   y => (predZ (addZ (neg n1) y)). *)
Fixpoint add1 (x2 : Z) (n : nat) {struct n} : Z :=
match n with
| O => succZ x2
| S n0 => succZ (add1 x2 n0)
end
with add2 (x2 : Z) (n : nat) {struct n} : Z :=
match n with
| O => predZ x2
| S n0 => predZ (add2 x2 n0)
end.
Definition addZ (x1 x2 : Z) : Z :=
match x1 with
| OZ => x2
| pos n => add1 x2 n
| neg n => add2 x2 n
end.
intro x; elim x; auto with arith.
intro n; elim n; auto with arith.
simpl in |- *.
intro y.
rewrite succ_predZ; auto with arith.
intros; symmetry  in |- *; rewrite addZ_eq5.
apply succ_predZ.
Qed.
intros; elim x.
reflexivity.
simple destruct n.
simpl in |- *; rewrite pred_succZ; trivial with arith.
intros; rewrite addZ_eq3; rewrite pred_succZ; trivial with arith.
trivial with arith.
Qed.
Proof addZ_eq3.
Proof addZ_eq5.
intros; elim x.
reflexivity.
simple induction n.
reflexivity.
intros.
do 2 rewrite (tech_add_pos_succZ n0).
elim H; reflexivity.
simple induction n.
simpl in |- *; symmetry  in |- *; apply succ_pred_pred_succZ.
intros.
do 2 rewrite (tech_add_neg_predZ n0).
rewrite H.
symmetry  in |- *; apply succ_pred_pred_succZ.
Qed.
intros; elim x.
reflexivity.
simple induction n.
simpl in |- *; apply succ_pred_pred_succZ.
intros.
do 2 rewrite (tech_add_pos_succZ n0).
rewrite H; apply succ_pred_pred_succZ.
simple induction n.
reflexivity.
intros.
do 2 rewrite (tech_add_neg_predZ n0).
elim H; reflexivity.
Qed.
simple induction x.
reflexivity.
simple induction n.
reflexivity.
intros; rewrite tech_add_pos_succZ; rewrite H; reflexivity.
simple induction n.
reflexivity.
intros; rewrite tech_add_neg_predZ; rewrite H; reflexivity.
Qed.
intros.
cut (succZ OZ = IZ); intros.
elim H.
rewrite (succ_addZ_r x OZ); rewrite (add_OZ x); reflexivity.
reflexivity.
Qed.
intros.
cut (predZ OZ = neg 0); intros.
elim H.
rewrite (pred_addZ_r x OZ); rewrite (add_OZ x); reflexivity.
reflexivity.
Qed.
Definition commutative (U : Set) (op : U -> U -> U) :=
forall x y : U, op x y = op y x.
unfold commutative in |- *; intros; elim x.
simpl in |- *; symmetry  in |- *; exact (add_OZ y).
simple induction n.
simpl in |- *; symmetry  in |- *; exact (add_IZ_succZ y).
intros; rewrite (tech_add_pos_succZ n0 y).
rewrite H.
cut (succZ (pos n0) = pos (S n0)); intros.
elim H0.
rewrite (succ_addZ_r y (pos n0)); reflexivity.
reflexivity.
simple induction n.
simpl in |- *; symmetry  in |- *; exact (add_mIZ_predZ y).
intros; rewrite (tech_add_neg_predZ n0 y).
rewrite H.
cut (predZ (neg n0) = neg (S n0)); intros.
elim H0.
rewrite (pred_addZ_r y (neg n0)); reflexivity.
reflexivity.
Qed.
simple induction n2.
intros; elim (addZ_commutativity (neg 0) (pos n1)).
rewrite addZ_eq4.
elim minus_n_Sm; trivial with arith.
elim minus_n_O.
apply tech_pred_posZ; trivial with arith.
intros; elim (addZ_commutativity (neg (S n)) (pos n1)).
rewrite tech_add_neg_predZ.
elim (addZ_commutativity (pos n1) (neg n)).
rewrite H; auto with arith.
elim (minus_n_Sm n1 (S n) H0).
apply tech_pred_posZ.
apply lt_minus2; trivial with arith.
Qed.
Definition associative (U : Set) (op : U -> U -> U) :=
forall x y z : U, op x (op y z) = op (op x y) z.

Theorem addZ_associativity : associative Z addZ.