Library Imp_LangTrick.UIPList


From Coq Require Import Arith Lia List.

Definition UIP (T:Type) := forall (x y:T) (H1 H2 : x = y), H1 = H2.

Definition sigma {X:Type} {x y : X} (H : x=y) : y=x := match H in (_=z) return z=x with eq_refl _ => eq_refl end.
Definition tau {X:Type} {x y z: X} (H1 : x=y) : y=z -> x=z := match H1 in (_=w) return w=z->x=z with eq_refl _ => fun H => H end.

Definition is_hedberg (X:Type) (f : forall (x y:X), x=y -> x=y) :=
  forall x y H1 H2, f x y H1 = f x y H2.

Lemma hedberg_to_UIP X f : is_hedberg X f -> UIP X.
Proof.
  intros H1 x y E1 E2.
  assert (forall (e:x=y), tau (f _ _ e) (sigma (f _ _ eq_refl)) = e) as Heq1.
  { intros e. destruct e. destruct (f x x eq_refl). easy. }
  rewrite <- (Heq1 E1).
  rewrite <- (Heq1 E2).
  rewrite (H1 x y E1 E2).
  reflexivity.
Qed.

Lemma list_ctor_law1 (X:Type) (h1 h2 : X) (t1 t2 : list X) : (h1::t1) = (h2::t2) -> h1 = h2.
Proof. intros H; congruence. Qed.
Lemma list_ctor_law2 (X:Type) (h1 h2 : X) (t1 t2 : list X) : (h1::t1) = (h2::t2) -> t1 = t2.
Proof. intros H; congruence. Qed.
Lemma list_ctor_law3 (X:Type) (h1 h2 : X) (t1 t2 : list X) : h1 = h2 -> t1 = t2 -> (h1::t1) = (h2::t2).
Proof. intros H1 H2; congruence. Qed.

Fixpoint UIP_list_hedberg (X:Type) (l1 l2 : list X) : l1 = l2 -> l1 = l2.
Proof.
  destruct l1 as [|l1h l1t]; destruct l2 as [|l2h l2t]; intros Heq; try (exfalso; congruence).
  - reflexivity.
  - apply list_ctor_law3.
    + eapply list_ctor_law1, Heq.
    + eapply (UIP_list_hedberg _), list_ctor_law2, Heq.
Defined.

Lemma UIP_list_is_hedberg (X:Type) (Huip : UIP X) : is_hedberg _ (UIP_list_hedberg X).
Proof.
  intros x y; induction x as [|xh xr IH] in y|-*; destruct y as [|yh yr]; intros E1 E2; try (exfalso; congruence).
  - cbn. easy.
  - cbn.
    erewrite (Huip _ _ (list_ctor_law1 X xh yh xr yr E1)).
    erewrite (IH _ (list_ctor_law2 X xh yh xr yr E1)).
    reflexivity.
Qed.

Lemma UIP_to_list (T : Type) : UIP T -> UIP (list T).
Proof.
  intros H x y. eapply hedberg_to_UIP. apply (UIP_list_is_hedberg _ H).
Qed.

Lemma pair_ctor_law1 (X : Type) (x1 x2 : X) (x1' x2' : X) : (x1, x2) = (x1', x2') -> x1 = x1'.
Proof. intros; congruence. Qed.
Lemma pair_ctor_law2 (X : Type) (x1 x2 : X) (x1' x2' : X) : (x1, x2) = (x1', x2') -> x2 = x2'.
Proof. intros; congruence. Qed.
Lemma pair_ctor_law3 (X:Type) (x1 x2 : X) (x1' x2' : X) : x1 = x1' -> x2 = x2' -> (x1, x2) = (x1', x2').
Proof. intros; congruence. Qed.

Fixpoint UIP_pair_hedberg (X:Type) (p1 p2 : X * X) : p1 = p2 -> p1 = p2.
Proof.
  destruct p1; destruct p2; intros Heq; try (exfalso; congruence).
  apply pair_ctor_law3.
  - eapply pair_ctor_law1, Heq.
  - eapply pair_ctor_law2, Heq.
Defined.

Lemma UIP_pair_is_hedberg (X:Type) (Huip : UIP X) : is_hedberg _ (UIP_pair_hedberg X).
Proof.
  intros x y; destruct x; destruct y; intros E1 E2; try (exfalso; congruence).
  cbn. erewrite (Huip _ _ (pair_ctor_law1 X x x0 x1 x2 E1)).
  erewrite (Huip _ _ (pair_ctor_law2 X x x0 x1 x2 E1)).
  reflexivity.
Qed.

Lemma UIP_to_pair (T : Type) : UIP T -> UIP (T * T).
Proof.
  intros H x y. eapply hedberg_to_UIP. apply (UIP_pair_is_hedberg _ H).
Qed.


Lemma option_ctor_law1 (X: Type) (x x': X) : Some x = Some x' -> x = x'.
Proof.
  intros. inversion H. reflexivity.
Qed.
Lemma option_ctor_law3' (X: Type) (x x': option X) :
  match x as x0, x' as x0' with
  | Some y, Some y' => y = y'
  | None, None => True
  | _, _ => False
  end -> x = x'.
Proof.
  intros. destruct x, x'.
  - congruence.
  - inversion H.
  - inversion H.
  - reflexivity.
Qed.

Fixpoint UIP_option_hedberg (X: Type) (p1 p2 : option X) : p1 = p2 -> p1 = p2.
Proof.
  destruct p1; destruct p2; intros Heq; try (exfalso; congruence).
  - apply option_ctor_law3'.
    eapply option_ctor_law1. assumption.
  - apply option_ctor_law3'. eapply I.
Defined.

Axiom UIP_None :
  forall (X: Type)
    (H1 H2: @None X = @None X),
    H1 = H2.

Lemma UIP_option_is_hedberg (X: Type) (Huip: UIP X) : is_hedberg _ (UIP_option_hedberg X).
Proof.
  intros x y; destruct x; destruct y; intros E1 E2; try (exfalso; congruence).
  - cbn. erewrite (Huip _ _ (option_ctor_law1 X x x0 E1)).
    reflexivity.
  - cbn. reflexivity.
Qed.

Lemma UIP_to_option (T: Type) : UIP T -> UIP (option T).
Proof.
  intros H x y. eapply hedberg_to_UIP. apply (UIP_option_is_hedberg _ H).
Qed.


Lemma UIP_to_option_pair (T: Type) (Huip_T: UIP T) :
  UIP (option (T * T)).
Proof.
  intros x y.
  eapply hedberg_to_UIP.
  eapply (UIP_option_is_hedberg _ (UIP_to_pair _ Huip_T)).
Qed.

Lemma UIP_option_pair_refl (T: Type) (Huip_T: UIPList.UIP T) :
  forall (o: option (T * T))
    (H: o = o),
    H = eq_refl.
Proof.
  pose proof (UIP_option := UIP_to_option_pair).
  specialize (UIP_option _ Huip_T).
  unfold UIP in UIP_option.
  intros. eapply UIP_option.
Qed.