Unfolding a proof term in Coq - 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.

Related

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.

refining types with modules and typeclasses

I'm not very familiar with modules or typeclasses in Coq, but based on my basic understanding of them, I believe I have a problem where I should use them.
I want to define a sum function that adds all the elements of a polymorphic list t. It should only work when the type of elements of the list (t) has some definition for plus_function and plus_id_element. The definition of sum I'd like to write would be something like this:
Fixpoint sum {t : Type} (l : list t) :=
match l with
| Nil => plus_id_element t
| Cons x xs => ((plus_function t) x (sum xs))
end.
I don't know what's the usual way to achieve something like this in Coq. I believe in Idris, for example, one would replace t by an interface/typeclass that defines plus_function and plus_id_element. Although typeclasses exist in Coq, I haven't seen them used very often and I believe people usually use modules instead to achieve something similar. I'm not sure if I'm mixing unrelated concepts. Are modules and typeclasses useful for this problem? What would be the recommended approach?
Indeed typeclasses were designed for this exact task, but then you face the hard problem of designing the particular class hierarchy that will fit your problem well.
Coq doesn't provide a standard hierarchy of mathematical operators, and there are many delicate trade-offs in building one with regard to the choice of classes, operators, and axioms.
I thus recommend starting from a mature development such as the MathComp library. MathComp is based on "Canonical Structures" which are a similar notion to type classes, and provides quite a few ready to use classes. The Packaging Mathematical Structures" paper contains more details, but the basic idea is that types pack their operators. For example, if you want to reason about abelian modules you can use the zmodType structure:
From mathcomp Require Import all_ssreflect all_algebra.
Open Scope ring_scope.
Definition sum (A: zmodType) (s : seq A) := foldr +%R 0 s.
to define the sum over a list of elements of the abelian group A. Even better, don't define you own sum operator and just use the one provided by the library: \sum_(x <- s) x:
Lemma eq_sum (A: zmodType) (s : seq A) : sum s = \sum_(x <- s) x.
Proof. by rewrite unlock. Qed.

General Advice about When to Use Prop and When to use bool

I am formalizing a grammar which is essentially one over boolean expressions. In coq, you can get boolean-like things in Prop or more explicitly in bool.
So for example, I could write:
true && true
Or
True /\ True
The problem is that in proofs (which is what I really care about) I can do a case analysis in domain bool, but in Prop this is not possible (since all members are not enumerable, I suppose). Giving up this tactic and similar rewriting tactics seems like a huge drawback even for very simple proofs.
In general, what situations would one choose Prop over bool for formalizing? I realize this is a broad question, but I feel like this is not addressed in the Coq manual sufficiently. I am interested in real world experience people have had going down both routes.
There are lots of different opinions on this. My personal take is that you are often better off not making this choice: it makes sense to have two versions of a property, one in Prop, the other one in bool.
Why would you want this? As you pointed out, booleans support case analysis in proofs and functions, which general propositions do not. However, Prop is more convenient to use in certain cases. Suppose you have a type T with finitely many values. We can write a procedure
all : (T -> bool) -> bool
that decides whether a boolean property P : T -> bool holds of all elements of T. Imagine that we know that all P = true, for some property P. We might want to use this fact to conclude that P x = true for some value x. To do this, we need to prove a lemma about all:
allP : forall P : T -> bool,
all P = true <-> (forall x : T, P x = true)
This lemma connects two different formulations of the same property: a boolean one and a propositional one. When reasoning about all in a proof, we can invoke allP to convert freely between the two. We can also have different conversion lemmas:
allPn : forall P,
all P = false <-> (exists x, P x = false)
In fact, we are free to choose any Coq proposition whatsoever to relate to a boolean computation (as long, of course, as we can prove that the two are logically equivalent). For instance, if we would like to have a custom induction principle associated with a boolean property, we can look for an equivalent formulation as an inductively defined proposition.
The Mathematical Components library is a good example of development that follows this style. Indeed, because it is so pervasive there, the library provides a special view mechanism for writing conversion lemmas like the one above and applying them. In plain Coq, we can also use the rewrite tactic to apply logical equivalences more conveniently.
Of course, there are many situations where it does not make sense to have two formulations of the same property. Sometimes, you are forced to use Prop, because the property you care about is undecidable. Sometimes, you might feel that you wouldn't gain anything by writing your property in Prop, and may keep it only as a boolean.
In addition to the Software Foundations chapter linked above, this answer discusses the difference between bool and Prop in more depth.

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 :\

Finish proof with false hypothesis in 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).