Confusing obligations generated by `Program` tactic - coq

I'm quite new to coq proof assistant and am still finding my feet.
I've encountered a case which I don't know how to deal with: I tried to use Program Fixpoint tactic to weaken the requirements on my code to later prove the needed properties afterwards as so called Obligations. While most of them were easy, there were two obligations generated goals of which had form [a-quite-simplee-xpr] = [my-function-name]_obligation_3, generally speaking the goals were refering to other obligations which were proved before. I tried unfolding and do substitutions but it didn't really help.
If there's no general solution for such problems I can send the proof script + the screenshot of the obligation to add some context.
Thank you in advance.

One thing that might be happening is that you have types which contain both "data" and "proof" (typically if you're trying to make refinement types with sig, or a custom inductive Type which contains proof terms), and that your functions require proofs of propositional equality, which is generally too strong for such dependent types.
Proof terms should be irrelevant: the simplest way out is to resolve that goal using an axiom from ProofIrrelevance (in the stdlib).
There are axiom-free ways, but I believe they require much more work/expertise.

Related

The foundations of Coq

I'm assuming Coq at some point moved to an LCF approach. In the past, I wondered about the foundations of the kernel in Isabelle. And I found some nice description of Isabelle/Pure in a master thesis summarizing somehow the existing literature.
I was wondering if there is a description of Coq's kernel covering the logical and implementation aspects of it.
I think your questions is similar to How does one implement Coq?.
At least I'm tempted to give a similar answer.
I think MetaCoq is the state-of-the-art effort to specify and (partially) verify the Coq kernel: https://github.com/MetaCoq/metacoq.
It is initially a library for meta-programming in Coq and as such implements a representation of the kernel inside Coq. It has evolved a lot and now contains the typing rules of (a subset of) Coq as well as formalisation of several meta-theoretical properties, a type-checker and an erasure mechanism.
Now understanding your question:
The Coq reference manual already offers some sort of specification of the Calculus of Inductive Constructions, which should always be up to date with the latest version of Coq.
The MetaCoq Project paper also attempts a specification of the predicative calculus of cumulative inductive constructions (PCUIC).
You seem to think that this somehow might have less value than a paper specification when done in the proof assistant itself, obviously I do not exactly think so (but I'm one of the authors, I'm biased). This is a fair concern, but at least as far as the specification is concerned, it only makes it much more precise than could be done on paper. The Coq reference manual can be imprecise at times. Our work also forces us to explicit invariants of representations that are not enforced in ocaml. Also we separate implementation and specification (the Coq reference manual is pretty implementation oriented). Arguably more works need to be done on this separation.
Otherwise, usually people treat subsets of these calculi, espcially regarding inductive types which are rather painful to lay out entirely.

How proof assistants are implemented?

What are the main blocks of a proof assistant?
I am just interested in knowing the internal logic of proof checking. For example, topics about graphical user interfaces of such assistants do not interest me.
A similar question to mine has been asked for compilers:
https://softwareengineering.stackexchange.com/questions/165543/how-to-write-a-very-basic-compiler
My concern is the same but for proof checking systems.
I'm hardly an expert on the matter (I'm only a user of these systems; I don't worry too much about their internals) and this will probably only be a vague partial answer, but the two main approaches that I know of are:
Dependently-typed systems (e.g. Coq, Lean, Agda) that use the Curry–Howard isomorphism. Statements are just types, and proofs are terms that have that type, so checking the validity of a proof is essentially just a special case of type checking a term. I don't want to say too much about this approach because I don't know too much about it and am afraid I'll get something wrong. Théo Winterhalter linked something in the comments above that may provide more context on this approach.
LCF-style theorems provers (e.g. Isabelle, HOL Light, HOL 4). Here a theorem is (roughly speaking) an opaque value of type thm in the implementation language. Only the comparatively small ‘proof kernel’ can create these thm values and all other parts of the system interact with this proof kernel. The kernel offers an interface consisting of various small functions that implement small inference steps such as modus ponens (if you have a theorem A ⟹ B and a theorem A, you can get the theorem B) or ∀-introduction (if you have the theorem P x for a fixed variable x, you can get the theorem ∀x. P x) etc. The kernel also offers an interface for defining new constants. In principle, as long as you can trust that these functions faithfully implement the basic inference steps of the underlying logic, you can trust that any thm value you can produce really corresponds to a theorem in your logic. For LCF-style provers, the answer of what the actual proof is is a bit more difficult to answer because they usually don't build proof terms (e.g. Isabelle has them, but they are disabled by default and not widely used). I think one could say that the history of how the kernel primitives are called constitute the proof, and if one were to record it, it could – in principle – be replayed and checked in another system.
In both cases the idea is that you have a kernel (the type checker in the former case and the inference kernel in the latter) that you have to trust, and then you have a large ecosystem of additional procedures around this to provide more convenience layers. Since they have to interact with the kernel in order to actually produce theorems, however, you do not have to trust that code.
All these different systems have various trade-offs about what parts of the system are in the kernel and what parts are not. In general, I think it is fair to say that the dependently-typed systems tend to have considerably larger kernels than the LCF-based ones (e.g. HOL Light has a particularly small and simple kernel).
There are also other systems that I believe do not fit into these two categories (e.g. Mizar, ACL2, PVS, Metamath, NuPRL) but I don't know anything about how these are implemented.
In the case of LCF, HOL and Isabelle, you'll find an extensive answer to your question in the journal article "From LCF to Isabelle/HOL". (It's open access.)
Most dependently typed systems, such as Coq, are also LCF-style theorem provers, as described in the article and in Eberl's answer. One significant difference is that such calculi incorporate full proof objects, so that one of the objectives of the LCF approach — to save space by not storing proofs — is abandoned. However, the objective of soundness is still met.

How to leverage auto's searching and hint databases in custom tactics?

In my coq development I am learning how to create new tactics tailored to my problem domain, a la Prof. Adam Chlipala. On that page he describes how to create powerful custom tactics by e.g. combining repeat with match.
Now, I already have a powerful one-shot tactic in use, auto. It strings together chains of steps found from hint databases. I have invested some effort in curating those hint databases, so I'd like to continue using it as well.
However this presents a problem. It isn't clear what the "right" way is to incorporate auto's functionality into customized tactics.
For example, since (per its page) auto always either solves the goal or does nothing, putting it inside a loop is no more powerful than calling it once after the loop.
To see why this isn't ideal, consider a hypothetical way to directly call a single "step" of auto, which succeeds if it could make a change (as opposed to only when it solved the goal) and fails otherwise. Such single-steps could be interleaved with custom behavior in a match repeat loop, allowing us to e.g. try contradiction or try congruence at intermediate points within the search tree.
Are there good design patterns for incorporating auto's functionality into custom tactics?
Can auto's behavior be decomposed into "single step" tactics that we can use?
What I would do instead would be to incorporate other tactics within auto.
You can do so by using the Hint Extern num pat => mytactic : mybase command where num is a priority number (0 being the highest priority), pat a pattern to filter when the hint should be used and mytactic and mybase are of course the tactic you want to apply and the base you want to add the hint to (do not use the default core; build up your custom base instead and call it with auto with mybase; if you do not want to include the lemmas from the core base in the search, add the fake base nocore: auto with mybase nocore).
If you start relying on auto very much, I would switch instead to the almost equivalent but better behaved typeclasses eauto with mybase. Contrary to what its name suggests, it is a general purpose tactic that has nothing to do with type classes (as long as you explicitly provide the hint base on which it should be working). One of the main behavior difference to know is that the search depth is unbounded by default. So beware of possible infinite loops or fix a finite limit with the variant typeclasses eauto num with mybase.

Is equality decidable on any coinductive type?

this is my first post, apologies if it I have made mistakes.
I suspect that, in Coq, coinductive types like Stream do not have decidable equality. That is, given two streams s and t, it is not possible identify whether s=t or ~(s=t). I suspect that this is true of all coinductive types in Coq.
A quick google and search through stack exchange does not reveal any confirmation. Can anyone confirm this or correct me?
I think you are right. To the best of my knowledge, you can't even correctly state what it means for two streams to be equal, since it would imply that you can inspect them in finite time, but they are infinite terms.
What you could do, is state that any finite inspection of your co-inductive terms are the same, or define a "co-inductive" notion of equality, much like it is done in the standard library:
https://coq.inria.fr/library/Coq.Lists.Streams.html

proving a theorem in Coq

I am trying to prove a theorem in Coq and I am not able to solve an issue that occurs. I am trying to solve:
forall A B C: Prop, A\/(B\/C)->(A\/B)\/C.
Proof.
intros.
destruct H as [H1 | [H2 | H3 ]].
Case H1.
and in this last line I get the following error "Error: The reference Case was not found in the current environment."
I am new to Coq so I do not know what that really means. I did some research on the Internet but I did not manage to find a solution. Does anyone have an idea of what this problem comes from?
You've destructed the hypothesis, so you're already analyzing each case.
Use left and right to manipulate the disjunction in the conclusion, and assumption when a hypothesis and the conclusion are the same.
EDIT: Hmm... I might have misunderstood what you were trying to do here actually...
The Case that you are using and have probably seen used elsewhere is not built in Coq, but rather is a library that has been floating around in the Coq ecosystem.
I can find a reference to it here: http://coq.inria.fr/cocorico/Case%20(tactic)
I have also used it personally. To use it, you need to either copy the definition in that link somewhere in your file, or in another file MyCaseModule.v that you import then:
Require Import MyCaseModule.
As a side-note, Coq 8.4 seems to offer another way to structure proofs using bullets. I do not know exactly the details, as I am stuck using 8.3 for other reasons. However, you might still prefer Case/SCase/... for its ability to give names to the different cases.