Require Import Coq.Bool.Bool.
Require Import Setoid.
Require Import Coq.Classes.Equivalence.
Require Import List.
Require Import ListSet.
Import ListNotations.
(* Law of Excluded Middle *)
Axiom excluded_middle: forall P : Prop, (P \/ ~P).
Record Group : Type := {
G :> Set;
op : G -> G -> G; (* operation *)
e : G; (* identity *)
inv: G -> G; (* inverse *)
assoc_law : forall (a b c : G), op a (op b c) = op (op a b) c;
id_law : forall (a : G), op a e = a /\ op e a = a;
inv_law : forall (a : G), op a (inv a) = e /\ op (inv a) a = e
}.
Arguments op {g} _ _.
Arguments e {g}.
Arguments inv {g} _.
Arguments assoc_law {g} _ _ _.
(* why do we need this *)
Notation "x <+> y" := (op x y) (at level 50, left associativity).
Definition is_identity (G : Group) (a : G) :=
forall (g : G), g <+> a = a /\ a <+> g = a.
(*
Theorem identity_op (G : Group): forall (a : G),
a <+> e = a /\ e <+> a = a.
Proof.
intros.
split; apply id_law.
Qed.
*)
Theorem identity_unique (G : Group): forall (a b: G),
((is_identity G a) /\ (is_identity G b)) -> a = b.
Proof.
intros.
unfold is_identity in H.
destruct H.
assert (a=b \/ a<>b). {
apply excluded_middle.
}
destruct H1.
+ tauto.
+
assert (a <+> b = a). { apply H. }
assert (a <+> b = b). { apply H0. }
rewrite <- H2.
apply H0.
Qed.
Definition has_inverse (G : Group) (a : G) :=
exists (a' : G), a<+>a'=e /\ a'<+>a=e.
Definition is_inverse (G : Group) (a : G) (b : G):=
a<+>b=e /\ b<+>a=e.
Theorem inverse_unique (G : Group): forall (a b g : G),
(is_inverse G a g /\ is_inverse G b g) -> a = b.
Proof.
unfold is_inverse.
intros.
destruct H as [[? ?] [? ?]].
assert (a=b \/ a<>b). {
apply excluded_middle.
}
destruct H3.
+ tauto.
+ assert (b <+> (g <+> a)= a). {
pose proof assoc_law b g a.
rewrite H4.
rewrite H1.
apply id_law.
}
assert (b <+> e = a). {
rewrite <- H0.
tauto.
}
rewrite <- H5.
apply id_law.
Qed.