Finish proof with false hypothesis in Coq - coq

So I have a false hypothesis in a subgoal. It's an equality between different constructors. How do I finish the subgoal?
H: List.Not_Empty Bit.Bit Bit.Zero (List.Empty Bit.Bit) = List.Empty Bit.Bit

This doesn't look like the Coq List I'm used to from the standard library, so it will be hard to help you without knowing the definitions of List.Not_Empty and List.Empty. If I guess correctly that List.Empty stands for nil and List.Not_empty stands for cons, then it's just a matter of showing that the two constructors are not equal. You can for instance do:
congruence.
or simply:
inversion H.
However, if it's something more involved, these two might fail. So you'd want to either:
SearchAbout List.Not_Empty.
to see if lemmas exist about it, or to:
unfold List.Not_Empty, List.Empty in H.
to unfold definitions and work out the details (possibly saving this subproof as a lemma if it does not exist, as it seems useful).

Related

Introducing a new assumption/hypothesis by adding it as subgoal

Let's suppose that I have the following proof state:
1 subgoal
P, Q : Prop
H : P -> Q
-------------------(1/1)
Q
and I know a way to prove P, how may I add an "inline proof" of it so that I can have it in my list of assumptions?
Another thing you can use is the pose proof tactic. This lets you actually supply the proof term and name it (pose proof (foo bar baz) as qux basically translates into let qux := foo bar baz in ... in the generated proof).
This can be neat for things like specialized versions of a lemma that you're going to use in multiple branches.
The tactic assert does exactly that.
Using assert (<proposition>) breaks your objective into two subgoals, in the first you have to prove "<proposition>" with your current assumptions, and the second has your original goal as the objective, but with "<proposition>" added to the list of assumptions.
You may also specify its name with assert (<proposition>) as <name> or assert (<name>: <proposition>).
Another option is to use cut (<proposition>).
It also creates two objectives, one of the form <proposition> -> <your objective> (then you can get your hypothesis by using intros, or intros <name> if you want to specify its name), and another one in which you have to prove "<prososition>" with your current assumptions.
If you use the SSRreflect proof language, you can use the have proof_of_P: P. <write your proof here> construct.

Proving technology of Coq's kernel

Isabelle bases its kernel proof power in resolution coupled with higher-order unification.
How are theorems proven by Coq's kernel?
The question arises from reading Paulson's "The foundation of a generic theorem prover":
Propositions-as-types could consume excessive space; and what would take the place of Huet's unification procedure for higher-order logic?
There are two kinds of technology in most provers: the "proving" part (responsible for building a proof, since it is often too tedious for the user) and the "checking" part (responsible for verifying that a proof is well-formed and matches a given theorem statement). In both Isabelle and Coq, the kernel is only responsible for the "checking" part.
In the case of Coq, the propositions-as-types paradigm is indeed used for checking proofs. In other words, a proof is a lambda-term of the Calculus of Inductive Constructions (CIC) whose type is compared to the theorem statement seen as a type.
How are theorems proven by Coq's kernel?
As explained above, theorems are not proven by Coq's kernel, only checked.
That check is done as usual with type checking: If the term is an application, check (recursively) that the arguments has the right type, and that the function return type matches the type. For example, to prove that a + f(b) has type nat, you must check that plus has type nat -> nat -> nat, that f has type A -> nat, that a has type nat and b has type A.
The proof has to be constructed by the user. The proof itself is a lambda term. The theorem proposition is the type of the lambda term.
Because it may be difficult to create the right lambda term directly, Coq does not force the user to write the whole term in one go. One can instead leave "holes" in the term to be filled in later, either by hand or with tactics. Tactics are small programs that try to fill in a piece of the proof (which may or may not be the right piece...).
Once the entire lambda term has been constructed, the proof is checked by Coq by checking that the lambda term really has the type of the proposition that one wishes to prove.

How to prove that "Type <> Set" (i.e. Type is not equal to Set) in Coq?

Is there an equality or inequality relation between Type and Set in Coq ?
I am learning about Coq's type system and understand that the type of Set is Type#{Set+1}, and that the type of Type#{k} is Type#{k+1}. I tried to prove that Type = Set, and then tried to prove Type <> Set, but I failed in both cases.
I started with
Lemma set_is_type : Type = Set.
Proof.
reflexivity.
which gives an error message saying that Unable to unify "Set" with "Type#{Top.74}".
Then I tried
Lemma set_is_not_type : Type <> Set.
Proof.
intros contra.
At this point I do not know how to proceed. The tactic discriminate did not work, neither inversion contra.
Which one of the above two lemmas can be proved?
This actually isn't an entirely trivial theorem. To show that Type = Set results in a paradox (and hence that having separate levels of Type is necessary), you'll need to use a standard result akin to Russell's paradox from set theory. Specifically, you'll need Hurken's paradox, which essentially says that smaller Types can't be on equal footing to larger Types (remember that Type is polymorphic in Coq, and in particular, Set is the lowest level (or second lowest if you include Prop)).
The particular theorem we want can be found in the standard library.
Require Logic.Hurkens.
Import Logic.Hurkens.TypeNeqSmallType.
Check paradox.
paradox has the type signature forall A : Type, Type = A -> False. This is pretty much what we want to prove, since Set: Type (at least if Type is large enough).
Lemma set_is_not_type: Type <> Set.
Proof.
intro F.
exact (paradox _ F).
Defined.
Coq automatically sets restrictions on the Type in this lemma to ensure that Set: Type.
On the other hand, Set is equal to some level of Type, so we should be able to prove that Type = Set with some different constraints on this Type. The easiest way I found to do this was to prove that Type = Type, but then instantiate this theorem with Set. For whatever reason, as you found, reflexivity can't enforce universe constraints by itself. To do this, we need to make both the lemmas universe polymorphic so that they can be instantiated with a particular universe level.
Polymorphic Lemma type_is_type: Type = Type.
Proof.
reflexivity.
Defined.
Polymorphic Lemma type_is_set: Type = Set.
Proof.
apply type_is_type.
Defined.
The easier way to make everything universe polymorphic is to put Set Universe Polymorphism. before everything.

Unfolding a proof term in Coq

I wonder if there is a way to obtain the proof term (serialized via Print or not) at some level beyond the current context (or just down to primitives). For example, executing the following
From mathcomp Require Import odd_order.PFsection14.
Print Feit_Thompson.
results in
Feit_Thompson =
fun (gT : fingroup.FinGroup.type)
(G : fingroup.group_of (gT:=gT)
(ssreflect.Phant
(fingroup.FinGroup.arg_sort
(fingroup.FinGroup.base gT)))) =>
BGsection7.minSimpleOdd_ind no_minSimple_odd_group (gT:=gT)
(G:=G)
: forall (gT : fingroup.FinGroup.type)
(G : fingroup.group_of (gT:=gT)
(ssreflect.Phant
(fingroup.FinGroup.arg_sort
(fingroup.FinGroup.base gT)))),
is_true
(ssrnat.odd
(fintype.CardDef.card
(T:=fingroup.FinGroup.arg_finType
(fingroup.FinGroup.base gT))
(ssrbool.mem
(finset.SetDef.pred_of_set
(fingroup.gval G))))) ->
is_true (nilpotent.solvable (fingroup.gval G))
but i would like to unfold the identifiers (theorems and definitions) used in the proof term such as no_minSimple_odd_group to their proof terms. I suspect that the opacity of theorems and lemmas might pose an obstacle to this purpose.
The naive solution i can think of is to recursively query each identifier via Print. Or a less naive (and less ideal due to the change in the language representing the proof term) solution, via program extraction.
I am not sure if there is a direct way of doing that, but it wouldn't be too hard to implement, at this level opacity is just a flag and can be bypassed.
However, I wonder about what do you want to achieve?
Note that most proof terms obtained that way are going to be just unmanageable, specially unfolding will quickly lead to a worse than exponential size blowup.

Lemma cannot be used as a hint

Why doesn't Coq accept this lemma as a hint?
Lemma contr : forall p1 : Prop, False -> p1.
Proof. tauto. Qed.
Hint Resolve contr : Hints.
Or other lemmas that end with a Prop variable?
Looking at the documentation for Hint Resolve ( http://coq.inria.fr/distrib/V8.4/refman/Reference-Manual011.html##command232 ):
term cannot be used as a hint
The type of term contains products over variables which do not appear in the conclusion. A typical example is a transitivity axiom. In that case the apply tactic fails, and thus is useless.
However, it does not seem (to me) to be the case here, as the only product is over p1 which does appear in the conclusion.
The problem here seems to be that your conclusion have absolutely no shape at all. auto seems to work by matching the shape of your goal with the shape of the return type of the hint database. Here, it might be upset by the fact that your goal is just a quantified variable. I am not sure whether this is a reasonable thing to trip over, but this particular instance might be the only case where you might have such a shapeless return type (with obviously the same case for Set and Type), so it's not a big deal.
So, you probably don't need this as a hint?... just use tactics such as tauto, intuition or perform any kind of elimination/destruction/inversion on the value of type False in your environment... not very satisfactory but eh :\