(* Addition on Z, (Z, +) is a group *)

(*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)).*)


(* this definition introduces unnecessary names *)


Fixpoint addpos (x2 : Z) (n : nat) {struct n} : Z :=
  match n with
  | O => succZ x2
  | S n0 => succZ (addpos x2 n0)
  end.Fixpoint addneg (x2 : Z) (n : nat) {struct n} : Z :=
  match n with
  | O => predZ x2
  | S n0 => predZ (addneg x2 n0)
  end.Definition addZ (x1 x2 : Z) :=
  match x1 with
  | OZ => x2
  | pos n => addpos x2 n
  | neg n => addneg x2 n
  end.

Lemma add_OZ : forall x : Z, addZ x OZ = x.