简体   繁体   中英

How to prove “~(nat = False)”, “~(nat = bool)” and “~(nat = True)” in coq

The following two propositions are easy to prove.

Theorem nat_eq_nat : nat = nat.
Proof.
  trivial.
Qed.

Theorem True_neq_False : ~(True = False).
Proof.
  unfold not.
  intros.
  symmetry in H.
  rewrite H.
  trivial.
Qed.

But when I tried to prove a slightly different proposition ~(nat = False) , I found the rewrite tactic doesn't work. It reports

Error: Refiner was given an argument "fun x : Set => x" of type "Set -> Set" instead of "Set -> Prop".

So I tried to write a lemma.

Lemma Type_eq_prod : forall (a : Type) (b : Type), a = b -> (a -> b).
Proof.
  intros.
  rewrite <- H.
  trivial.
Qed.

Theorem nat_neq_False : ~(nat = False).
Proof.
  unfold not.
  intros.
  apply (Type_eq_prod nat False) in H.
  inversion H.
  apply 0. (*no subgoals left*)

All works fine until now. But when I tried to Qed it, it reported

Error: Illegal application (Type Error): 
The term "Type_eq_prod" of type "forall a b : Type, a = b -> a -> b"
cannot be applied to the terms
 "nat" : "Set"
 "False" : "Prop"
 "H" : "nat = False"
 "0" : "nat"
The 3rd term has type "nat = False" which should be coercible to
 "nat = False".

The following are another two propositions that make me stuck.

Theorem nat_neq_bool : ~(nat = bool).
Proof.
  unfold not.
  intros.
Abort.

Theorem nat_neq_true : ~(nat = True).
Proof.
  unfold not.
  intros.
Abort.

My questions are:

 1.Why the rewrite tactic doesn't work with proposition ~(nat = False).
 2.Why can't I Qed it when there is no subgoals.
 3.How to prove the aborted propositions above or is it possible to prove or prove the negates of them in coq.
  1. The rewrite tactic doesn't work due to how Coq handles its universes, Prop , Set and Type . There is a notion of subsumption which allows one to use a Prop as if it were a Set or a Type . This is why you were allowed to write nat = False in the first place, since equality is only allowed between things of the same type. The problem is that, for Coq, False : Prop is different from False : Set . not is defined with False : Prop , which means that that rewrite will produce a mismatch, which explains the error message you got.

    Here are similar approaches that would work. Notice the explicit coercion to Set .

     Lemma nat_neq_False_2 : (nat = False) -> (False : Set). Proof. intros H. rewrite <- H. apply 0. Qed. Lemma nat_neq_False_3 : ~(nat = False). Proof. intros H. destruct (nat_neq_False_2 H). Qed. 
  2. When you write a proof using tactics, Coq is essentially building a proof term internally, but isn't really typechecking it. In this sense, it is a little bit like metaprogramming. Once you hit Qed , the term that was built by the tactic is sent to the typechecker to make sure it is OK. Most of the times, tactics produce proofs that are correct, but every once in a while one finds proofs that are not accepted, and your case is an example of that.

    The error message that was printed was not very clear, but one can get a better sense of what's happening by using the command Set Printing All , which causes Coq to print all terms and statements without notations and showing implicit arguments. This is what your error message becomes when doing that:

     Set Printing All. Lemma Type_eq_prod : forall (a : Type) (b : Type), a = b -> (a -> b). Proof. intros. rewrite <- H. trivial. Qed. Theorem nat_neq_False : ~(nat = False). Proof. unfold not. intros. apply (Type_eq_prod nat False) in H. inversion H. apply 0. (*no subgoals left*) Qed. (* Error: Illegal application (Type Error): *) (* The term "Type_eq_prod" of type "forall ab : Type, @eq Type ab -> a -> b" *) (* cannot be applied to the terms *) (* "nat" : "Set" *) (* "False" : "Prop" *) (* "H" : "@eq Set nat False" *) (* "O" : "nat" *) (* The 3rd term has type "@eq Set nat False" which should be coercible to *) (* "@eq Type nat False". *) 

    There, we can see that the problem is that there is again a universe mismatch: one equality is in Type , while the other is in Set . There are several ways one can fix this; the easiest is probably to change your first theorem to:

     Lemma Type_eq_prod : forall (a : Set) (b : Set), a = b -> (a -> b). 
  3. Both propositions are provable in Coq. In the base theory of Coq, the only way one can show that simple types such as nat and bool are different is by cardinality arguments. Thus, nat <> bool because bool has only two elements, whereas nat has more than that. Thus, by showing that bool has two elements, one can rewrite the equality nat = bool to find out that nat should also have two elements, and then exploit that to get a contradiction. A similar argument would show that nat <> True .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM