Proof of the isomorphism between the Martin-Lof equality and path induction in Coq

I am studying Coq and trying to prove an isomorphism between Martin-Lof equality and Path Induction.

I have defined two equalities as follows.

Module MartinLof.

Axiom eq : forall A, A -> A -> Prop.
Axiom refl : forall A, forall x : A, eq A x x.
Axiom el : forall (A : Type) (C : forall x y : A, eq A x y -> Prop),
  (forall x : A, C x x (refl A x)) ->
    forall a b : A, forall p : eq A a b, C a b p.

End MartinLof.

Module PathInduction.
Axiom eq : forall A, A -> A -> Prop.
Axiom refl : forall A, forall x : A, eq A x x.
Axiom el : forall (A : Type) (x : A) (P : forall a : A, eq A x a -> Prop), 
    P x (refl A x) -> forall y : A, forall p : eq A x y, P y p.

End PathInduction.

      

And I have defined the two functions involved in isomorphism as follows.

Definition f {A} : forall x y: A, forall m: MartinLof.eq A x y, PathInduction.eq A x y.
Proof.
apply: (MartinLof.el A (fun a b p => PathInduction.eq A a b) _ x y m).
move=> x0.
exact: PathInduction.refl A x0.
Defined.

Definition g {A} : forall x y: A, forall p: PathInduction.eq A x y, MartinLof.eq A x y.
Proof.
apply: (PathInduction.el A x (fun a p => MartinLof.eq A x a) _ y p).
exact: MartinLof.refl A x.
Defined.

      

Now I'm trying to define the following validation terms, but I can't get past the original statement because I really don't know what tactics to apply.

Definition pf1 {A}:  forall x y: A, forall m: MartinLof.eq A x y,
  eq m (g x y (f x y m)).

Definition pf2 {A} : forall x y: A, forall p: PathInduction.eq A x y, 
  eq p (f x y (g x y p)).

      

Through I I could simplify the expression

(g x y (f x y m))

      

but i dont know how to do it. Does anyone know how I can proceed with this proof?

Thanks in advance.

+3


source to share


1 answer


The problem is that your definition of the types of identifiers is incomplete as it doesn't specify how it el

interacts with refl

. Here is the complete solution.

From mathcomp Require Import ssreflect.

Module MartinLof.

Axiom eq : forall A, A -> A -> Prop.
Axiom refl : forall A, forall x : A, eq A x x.
Axiom el : forall (A : Type) (C : forall x y : A, eq A x y -> Prop),
  (forall x : A, C x x (refl A x)) ->
    forall a b : A, forall p : eq A a b, C a b p.
Axiom el_refl : forall (A : Type) (C : forall x y : A, eq A x y -> Prop)
    (CR : forall x : A, C x x (refl A x)),
    forall x : A, el A C CR x x (refl A x) = CR x.

End MartinLof.

Module PathInduction.
Axiom eq : forall A, A -> A -> Prop.
Axiom refl : forall A, forall x : A, eq A x x.
Axiom el : forall (A : Type) (x : A) (P : forall a : A, eq A x a -> Prop),
    P x (refl A x) -> forall y : A, forall p : eq A x y, P y p.
Axiom el_refl : forall (A : Type) (x : A) (P : forall y : A, eq A x y -> Prop)
    (PR : P x (refl A x)),
    el A x P PR x (refl A x) = PR.

End PathInduction.

Definition f {A} (x y: A) (m: MartinLof.eq A x y) : PathInduction.eq A x y.
Proof.
apply: (MartinLof.el A (fun a b p => PathInduction.eq A a b) _ x y m).
move=> x0.
exact: PathInduction.refl A x0.
Defined.

Definition g {A} (x y: A) (p: PathInduction.eq A x y) : MartinLof.eq A x y.
Proof.
apply: (PathInduction.el A x (fun a p => MartinLof.eq A x a) _ y p).
exact: MartinLof.refl A x.
Defined.

Definition pf1 {A} (x y: A) (m: MartinLof.eq A x y) : eq m (g x y (f x y m)).
Proof.
apply: (MartinLof.el A (fun x y p => p = g x y (f x y p))) => x0.
by rewrite /f MartinLof.el_refl /g PathInduction.el_refl.
Qed.

Definition pf2 {A} (x y: A) (m: PathInduction.eq A x y) : eq m (f x y (g x y m)).
Proof.
apply: (PathInduction.el A x (fun y p => p = f x y (g x y p))).
by rewrite /f /g PathInduction.el_refl MartinLof.el_refl.
Qed.

      

Alternatively, you could simply define the two identity types as inductive Coq types, which would provide you with the same principles without having to specify separate axioms; The Coq calculation behavior already gives you the equations you need. I've used the pattern matching syntax, but similar definitions are possible using the standard combinators eq1_rect

and eq2_rect

.

Inductive eq1 (A : Type) (x : A) : A -> Type :=
| eq1_refl : eq1 A x x.

Inductive eq2 (A : Type) : A -> A -> Type :=
| eq2_refl x : eq2 A x x.

Definition f {A} {x y : A} (p : eq1 A x y) : eq2 A x y :=
  match p with eq1_refl _ _ => eq2_refl A x end.

Definition g {A} {x y : A} (p : eq2 A x y) : eq1 A x y :=
  match p with eq2_refl _ z => eq1_refl A z end.

Definition fg {A} (x y : A) (p : eq2 A x y) : f (g p) = p :=
  match p with eq2_refl _ _ => eq_refl end.

Definition gf {A} (x y : A) (p : eq1 A x y) : g (f p) = p :=
  match p with eq1_refl _ _ => eq_refl end.

      



Although not immediately clear, eq1

matches yours PathInduction.eq

, but eq2

matches yours MartinLof.eq

. You can check this by asking Coq to print the types of their recursion principles:

Check eq1_rect.
Check eq2_rect.

      

You may notice that I have defined two in Type

instead of Prop

. I just did it to make the recursion principles Coq created closer to the ones you had; by default Coq uses simpler recursion principles for the things defined in Prop

(although this behavior can be changed with a few commands).

+2


source







All Articles