1

I have a query about inductively defined relation eq in Coq. Consider the following definition of eq in Coq:

Inductive eq (A : Type) (x : A) : A -> Prop :=  eq_refl : x = x

This is an inductively defined relation just like le (<=). Therefore I should be able to do case analysis on any evidence of this type. However, when I tried proving the following result I could not succeed.

Lemma true_num: forall m :nat, forall x y: m=m, x=y.
  Proof. intros. destruct x.

(// Error: Abstracting over the terms "m" and "x" leads to a term
fun (m0 : nat) (x0 : m0 = m0) => x0 = y
which is ill-typed.
Reason is: Illegal application: 
The term "@eq" of type "forall A : Type, A -> A -> Prop"
cannot be applied to the terms
 "m0 = m0" : "Prop"
 "x0" : "m0 = m0"
 "y" : "m = m"
The 3rd term has type "m = m" which should be coercible to 
"m0 = m0". )  

I am unable to decode this error.

The only proof for m=m should be @eq_refl nat m since eq_refl is the only constructor. Hence one should be able to prove the equality of x and y by doing case analysis.

What is wrong with this line of reasoning?

  • [This](https://stackoverflow.com/questions/35157052/coq-identity-term-which-is-not-eq-refl) is related. – Anton Trunov Jan 09 '18 at 09:49
  • @AntonTrunov This seems to be the real problem. Reading the discussion I could see that the goal is provable. However, I was wondering why is it so difficult to prove such a thing by just doing case analysis in Coq. There is only one constructor for this type. – Abhishek Kr Singh Jan 09 '18 at 16:19
  • Indeed your lemma is a special case of `UIP_nat` defined in [Coq.Arith.Peano_dec](https://github.com/coq/coq/blob/6c678a68c081ce24bbdcb092db3f57ef7e171dac/theories/Arith/Peano_dec.v#L31). UIP holds for the types with decidable equality. To better understand what is going on here I suggest to read the [Equality](http://adam.chlipala.net/cpdt/html/Equality.html) chapter of CPDT book (`lemma3` seems to be the most relevant). – Anton Trunov Jan 09 '18 at 17:08

2 Answers2

2

The error is due to the way destruct works, recall that the tactic tries to build a match statement, and in order to do so it has some heuristics as to bring dependent hypotheses into context.

In particular, in this case it tries to abstract over the variable m, which is an index to the eq inductive in y : m = m; however y is not brought into context, hence the error as m != m0 [with m0 being the abstracted m]. You can workaround that problem it by doing a "less smart" match, which won't modify m:

refine (match x with | @eq_refl _ _ => _ end).

but usually, the best solution is to bring the hypothesis at fault into scope:

revert y; destruct x.

On the other hand, to prove your goal simple pattern-matching won't suffice as pointed out by the other excellent answers. My preferred practical approach to solve goals like yours is to use a library:

From mathcomp Require Import all_ssreflect.

Lemma true_num (m : nat) (x y : m = m) : x = y.
Proof. exact: eq_irrelevance. Qed.

In this case, the proper side conditions for the nat type are inferred automatically by the machinery of the library.

ejgallego
  • 6,709
  • 1
  • 14
  • 29
  • This solves the case analysis on x. However, eventually I wish to do case analysis on y as well. So in the second destruct on y its again fails with the following error: Error: Cannot instantiate metavariable P of type "forall a : nat, m = a -> Prop" with abstraction "fun (m : nat) (y : m = m) => eq_refl = y" of incompatible type "forall m : nat, m = m -> Prop". – Abhishek Kr Singh Jan 09 '18 at 15:49
  • where can I get more details about the working of destruct (its implementation)? – Abhishek Kr Singh Jan 09 '18 at 16:04
  • Is there some other more efficient tactic in Coq to do case analysis on evidence of this type? – Abhishek Kr Singh Jan 09 '18 at 16:07
  • The most common one is the `rewrite` tactic. – ejgallego Jan 09 '18 at 18:18
  • 1
    This is a red herring; the question is isomorphic to asking why Axiom K is independent from Coq, which has to do with the implementation of `match`, but nothing to do with the implementation of `destruct ` or `rewrite `. – Jason Gross Jan 10 '18 at 06:52
  • Maybe @JasonGross, honestly I am having trouble trying to understand what the OP would like to do. – ejgallego Jan 10 '18 at 10:47
  • To me it sounds like the OP wants to prove `forall m :nat, forall x y: m=m, x=y` by `destruct x, y; reflexivity ` and wants to know why this isn't working, i.e., why we can't say that since the only proof of `m=m` is `eq_refl `, it suffices to prove `eq_refl = eq_refl `. – Jason Gross Jan 10 '18 at 14:13
  • Oh indeed, I didn't even look at the ultimate goals, answer edited, merci. – ejgallego Jan 10 '18 at 14:30
1

The only proof for m=m should be @eq_refl nat m since eq_refl is the only constructor

No. Your theorem happens to be true because you are talking about equality of nat, but your reasoning goes through just as well (or poorly) if you replace nat with Type, and replacing nat with Type makes the theorem unprovable.

The issue is that the equality type family is freely generated by the reflexively proof. Therefore, since everything in Coq respects equality in the right way (this is the bit I'm a bit fuzzy on), to prove a property of all proofs of equality in a family (i.e. all proofs of x = y for some fixed x and for all y), it suffices to prove the property of the generator, the reflexively proof. However, once you fix both endpoints, so to speak, you no longer have this property. Said another way, the induction principle for eq is really an induction principle for { y | x = y }, not for x = y. Similarly, the induction principle for vectors (length-indexed lists) is really an induction principle for { n & Vector.t A n }.

To decode the error messages, it might help to try manually applying the induction principle for eq. The induction principle states: given a type A, a term x : A, and a property P : forall y : A, x = y -> Prop, to prove P y e for any given y : A and any proof e : x = y, it suffices to prove P x eq_refl. (To see why this makes sense, consider the non dependent version: given a type A, a term x : A, and a property P : A -> Prop, for any y : A and any proof e : x = y, to prove P y, it suffices to prove P x.)

If you try applying this by hand, you will find that there is no way to construct a well-typed function P when you are trying to induct over the second proof of equality.

There is an excellent blog post that explains this in much more depth here: http://math.andrej.com/2013/08/28/the-elements-of-an-inductive-type/

Jason Gross
  • 5,928
  • 1
  • 26
  • 53