Library Coqtail.Hierarchy.Type_class_instance


Require Import RelationClasses.
Require Import Type_class_definition.
Require Import Omega.



Instance monoid_nat : Monoid nat eq plus 0 :=
{monoid_iden_l := plus_0_l}.
Proof.
int_hierarchy.
int_hierarchy.
int_hierarchy.
int_hierarchy.
Qed.

Instance monoid_commutative_nat : Monoid_Commutative nat eq plus 0 :=
{monoid_comm_monoid := monoid_nat}.
Proof.
int_hierarchy.
Qed.

Instance monoid_nat_mult_1 : Monoid nat eq mult 1 :=
{monoid_iden_l := mult_1_l }.
Proof.
int_hierarchy.
int_hierarchy.
int_hierarchy.
int_hierarchy.
Qed.

Instance semiring_nat : SemiRing nat eq plus mult 0 1 :=
{semiring_monoid_comm := monoid_commutative_nat}.
Proof.
int_hierarchy.
int_hierarchy.
int_hierarchy.
int_hierarchy.
Qed.

Instance semiring_commutative_nat : SemiRing_Commutative nat eq plus mult 0 1 :=
{semiring_comm_semiring := semiring_nat}.
Proof.
int_hierarchy.
Qed.


Instance monoid_Z : Monoid Z eq Zplus 0%Z :=
{monoid_iden_l := Zplus_0_l}.
Proof.
int_hierarchy.
int_hierarchy.
int_hierarchy.
int_hierarchy.
Qed.

Instance monoid_mult_Z : Monoid Z eq Zmult 1%Z :=
{monoid_iden_l := Zmult_1_l}.
Proof.
int_hierarchy.
int_hierarchy.
int_hierarchy.
int_hierarchy.
Qed.

Instance group_Z : Group Z eq Zplus 0%Z :=
{group_monoid := monoid_Z}.
Proof.
intro x; (-x)%Z.
int_hierarchy.
Qed.

Instance group_commutative_Z : Group_Commutative Z eq Zplus 0%Z :=
{group_comm_group := group_Z}.
Proof.
int_hierarchy.
Qed.

Instance ring_Z : Ring Z eq Zplus Zmult 0%Z 1%Z :=
{ring_group_comm := group_commutative_Z}.
Proof.
int_hierarchy.
int_hierarchy.
Qed.

Instance ring_commutative_Z : Ring_Commutative Z eq Zplus Zmult 0%Z 1%Z :=
{ring_comm_ring := ring_Z}.
Proof.
int_hierarchy.
Qed.

Section Z_nZ.

Require Import ZArith.
Require Import Znumtheory.

Hypothesis n : Z.
Definition mod_eq x y := ( n | y - x ).
Notation "x %= y" := (mod_eq x y) (at level 0).

Lemma mod_eq_refl : Reflexive mod_eq.
Proof.
intro.
unfold mod_eq.
ring_simplify.
auto with ×.
Qed.

Lemma mod_eq_sym : Symmetric mod_eq.
Proof.
repeat intro.
destruct H as [q H].
(-q).
rewrite Zopp_mult_distr_l_reverse.
rewrite <- H.
ring.
Qed.

Lemma mod_eq_trans : Transitive mod_eq.
Proof.
intros q1 q2 q3 Hl Hr. destruct Hl as [q4 Hl], Hr as [q5 Hr]; (q4 + q5).
rewrite Zmult_plus_distr_l; rewrite <- Hl; rewrite <- Hr; ring.
Qed.


Instance mod_eq_equiv : Equivalence mod_eq.
Proof.
constructor; auto with modarith.
Qed.

Lemma Zmod_plus_0_l : x : Z, (0 + x) %= x.
Proof.
intro; unfold mod_eq; ring_simplify; apply Zdivide_0.
Qed.

Lemma Zmod_plus_0_r : x : Z, (x + 0) %= x.
Proof.
intros; rewrite Zplus_comm; apply Zmod_plus_0_l.
Qed.

Lemma Zmod_plus_compat_r: x y z : Z, x %=y(x+z) %= (y+z).
Proof.
intros; unfold mod_eq in H; unfold mod_eq; rewrite Zminus_plus_simpl_r; exact H.
Qed.

Lemma Zmod_plus_compat_l: x y z : Z, y %=z(x+y) %= (x+z).
Proof.
intros; unfold mod_eq in H; unfold mod_eq; rewrite Zminus_plus_simpl_l; exact H.
Qed.

Instance mod_eq_plus_assoc : Associative mod_eq Zplus.
Proof.
repeat intro; unfold mod_eq; ring_simplify; apply Zdivide_0.
Qed.

Lemma Zmod_mult_1_r : x : Z, (x × 1) %= x.
Proof.
intro; ring_simplify; apply mod_eq_refl.
Qed.

Lemma Zmod_mult_1_l : x : Z, (1 × x) %= x.
Proof.
intro; rewrite Zmult_comm; apply Zmod_mult_1_r.
Qed.

Lemma Zmod_mult_compat_l : x y z : Z, y%=z(x×y) %= (x×z).
Proof.
intros x y z [q H]; unfold mod_eq in ×.
apply Zdivide_intro with (x×q).
rewrite <- Zmult_minus_distr_l with z y x.
rewrite H.
rewrite Zmult_assoc.
reflexivity.
Qed.

Lemma Zmod_mult_compat_r : x y z : Z, x%=y(x×z) %= (y×z).
Proof.
intros x y z [q H]; unfold mod_eq in H; unfold mod_eq.
apply Zdivide_intro with (z×q).
rewrite <- Zmult_minus_distr_r with y x z.
rewrite H.
rewrite Zmult_comm.
rewrite Zmult_assoc.
reflexivity.
Qed.

Instance monoid_Z_nZ : Monoid Z mod_eq Zplus 0%Z :=
{monoid_iden_l := Zmod_plus_0_l}.
Proof.
apply Zmod_plus_0_r.
apply Zmod_plus_compat_l.
apply Zmod_plus_compat_r.
Qed.

Instance mod_eq_mult_assoc : Associative mod_eq Zmult.
Proof.
repeat intro; ring_simplify; apply mod_eq_refl.
Qed.

Instance monoid_mult_Z_nZ : Monoid Z mod_eq Zmult 1%Z :=
{monoid_iden_l := Zmod_mult_1_l}.
Proof.
apply Zmod_mult_1_r.
apply Zmod_mult_compat_l.
apply Zmod_mult_compat_r.
Qed.

Lemma mod_eq_plus_invert : x : Z, sig (fun y(x + y) %= 0).
Proof.
intros; (-x); ring_simplify; apply mod_eq_refl.
Qed.

Instance group_Z_nZ : Group Z mod_eq Zplus 0%Z :=
{group_monoid := monoid_Z_nZ}.
Proof.
apply mod_eq_plus_invert.
Qed.

Instance Zmod_plus_comm : Commutative mod_eq Zplus.
Proof.
repeat intro; rewrite Zplus_comm; apply mod_eq_refl.
Qed.

Instance group_commutative_Z_nZ : Group_Commutative Z mod_eq Zplus 0%Z :=
{group_comm_group := group_Z_nZ}.

Lemma Zmod_mult_plus_distr_r : n m p : Z, (n × (m + p)) %= (n × m + n × p).
Proof.
intros; ring_simplify; apply mod_eq_refl.
Qed.

Lemma Zmod_mult_plus_distr_l : n m p : Z, ((n + m) × p) %= (n × p + m × p).
Proof.
intros; ring_simplify; apply mod_eq_refl.
Qed.

Instance ring_Z_nZ : Ring Z mod_eq Zplus Zmult 0%Z 1%Z :=
{ring_group_comm := group_commutative_Z_nZ}.
Proof.
apply Zmod_mult_plus_distr_r.
apply Zmod_mult_plus_distr_l.
Qed.

Instance Zmod_mult_comm : Commutative mod_eq Zmult.
Proof.
repeat intro; rewrite Zmult_comm; apply mod_eq_refl.
Qed.

Instance ring_commutative_Z_nZ : Ring_Commutative Z mod_eq Zplus Zmult 0%Z 1%Z :=
{ring_comm_ring := ring_Z_nZ}.

End Z_nZ.

Section Fp.

Require Import ZArith.
Require Import Znumtheory.

Hypothesis p : Z.
Hypothesis p_prime : prime p.
Definition rel := mod_eq p.
Notation "x %= y" := (rel x y) (at level 0).

Lemma Zmult_iden_l : x : Z, (1 × x) %= x.
Proof.
intros.
ring_simplify; apply mod_eq_refl.
Qed.

Lemma Zmult_iden_r : x : Z, (x × 1) %= x.
Proof.
intros.
rewrite Zmult_comm; apply Zmult_iden_l; assumption.
Qed.

Section ConstructiveZ.
  Require Import ConstructiveEpsilon.
  Variable P : ZProp.
  Hypothesis P_decidable : x, {P x} + {¬ P x}.

  Theorem constructive_indefinite_description_Z : ex Psig P.
  Proof.
    intros H.
    case (P_decidable 0).
     intro.
     econstructor.
     eauto.

     intro nP0.
     pose (fun nP (Z_of_nat n) P (- Z_of_nat n)) as P'.
     assert (ex P').
      destruct H as [z].
       (Zabs_nat z).
      destruct z; [contradiction | left | right];
       simpl; rewrite <- Zpos_eq_Z_of_nat_o_nat_of_P; assumption.
     destruct (constructive_indefinite_description_nat P').
      intro n.
      unfold P'.
      destruct P_decidable with (Z_of_nat n); intuition.
      destruct P_decidable with (- Z_of_nat n); intuition.

      assumption.

     destruct P_decidable with (Z_of_nat x).
      econstructor; apply p1.
      destruct P_decidable with (- Z_of_nat x).
       econstructor; apply p1.
       subst P'; simpl in ×.
       assert False by tauto.
       contradiction.
  Defined.
End ConstructiveZ.

Lemma Zmult_reverse : x : Z, ¬ x %= 0 → sig (fun y(x × y) %= 1).
Proof.
intros.
apply constructive_indefinite_description_Z.
 intro.
 unfold "%=", mod_eq.
 apply Zdivide_dec.
cut (Zis_gcd x p 1).
 intro H0; destruct (Zis_gcd_bezout _ _ _ H0) as [u v H1].
  u; v.
 rewrite <- H1; ring.
constructor; try apply Zone_divide.
intros.
assert (Zabs x0Zabs p) by (apply Zdivide_bounds; trivial; destruct p_prime; omega).
replace (Zabs p) with p in H2 by (destruct p; trivial; destruct p_prime; inversion H3).
assert( x1, 0x1p (x1 | x) (x1 | p) Zabs x0 = x1).
 destruct x0.
  destruct H1; ring_simplify in H1; destruct p_prime; subst; inversion H3.
   (Zpos p0); repeat split; auto; apply Zle_0_pos.
   (-Zneg p0); repeat split; try rewrite Zopp_neg; auto with ×.
clear H0 H1 H2.
destruct H3; destruct H0; destruct H1; destruct H0; destruct H2.
cut (x1 | 1).
 intro; destruct x0; simpl in H4; try (subst; assumption).
 apply Zdivide_opp_l_rev; rewrite Zopp_neg; rewrite H4; assumption.
destruct (dec_Zle x1 1).
 apply Zle_lt_or_eq in H0.
 destruct H0.
  replace x1 with 1 by (apply Zlt_le_succ in H0; simpl in H0; apply Zle_antisym; assumption).
  apply Zone_divide.

  rewrite <- H0 in H2; destruct H2; ring_simplify in H2.
  destruct p_prime; rewrite H2 in H6; inversion H6.

 apply Znot_le_gt in H5.
 destruct (dec_Zlt x1 p).
  destruct p_prime.
  apply (H8 x1).
   split; omega.
   apply Zdivide_refl.
   assumption.

  apply False_ind; apply H.
  ring_simplify.
  apply Zdivide_opp_r.
  replace p with x1 by (apply Zle_antisym; omega).
  assumption.
Qed.

Lemma Zmult_compat_l: x y z : Z, (y) %= (z)(x × y) %= (x × z).
Proof.
intros.
unfold rel; unfold mod_eq; unfold rel in H; unfold mod_eq in H.
destruct H as [q H].
apply Zdivide_intro with (x×q).
rewrite <- Zmult_minus_distr_l.
rewrite H.
rewrite Zmult_assoc.
reflexivity.
Qed.

Lemma Zmult_compat_r: x y z : Z, (x) %= (y)(x × z) %= (y × z).
Proof.
intros.
unfold rel; unfold mod_eq; unfold rel in H; unfold mod_eq in H.
destruct H as [q H].
apply Zdivide_intro with (z×q).
rewrite <- Zmult_minus_distr_r.
rewrite H.
rewrite Zmult_comm.
rewrite Zmult_assoc.
reflexivity.
Qed.

Instance group_multiplicative_Fp : Group_Multiplicative Z rel Zmult 0 1 :=
{group_setoid := mod_eq_equiv p}.
Proof.
apply Zmult_iden_l.
apply Zmult_iden_r.
apply Zmult_reverse.
apply mod_eq_mult_assoc.
apply Zmult_compat_l.
apply Zmult_compat_r.
Qed.

Instance field_Fp : Field Z rel Zplus Zmult 0%Z 1%Z :=
{field_group_comm := group_commutative_Z_nZ p}.
Proof.
apply Zmod_mult_plus_distr_r.
apply Zmod_mult_plus_distr_l.
Qed.

Instance field_commutative_Fp : Field_Commutative Z rel Zplus Zmult 0%Z 1%Z :=
{field_comm_field := field_Fp}.
Proof.
apply Zmod_mult_comm.
Qed.

End Fp.