Extensionally equal predicates and equality of universally quantified applications - coq

I am trying to define a recursive predicate using well-founded fixpoints with the obligation to show F_ext when rewriting with Fix_eq. The CPDT says that most such obligations are dischargeable with straightforward proof automation, but unhappily this does not appear to be so for my predicate.
I have reduced the problem to the following lemma (from Proper (pointwise_relation A eq ==> eq) (#all A)). Is it provable in Coq without additional axioms?
Lemma ext_fa:
forall (A : Type) (f g : A -> Prop),
(forall x, f x = g x) ->
(forall x, f x) = (forall x, g x).
It can be shown with extensionality of predicates or functions, but since the conclusion is weaker than the usual one (f = g) I naively thought it would be possible to produce a proof without using additional axioms. After all, both sides of the equality only involve applications of f and g; how could any intensional differences be discerned?
Have I missed a simple proof or is the lemma unprovable?

You might be interested in this code I wrote a while ago, which includes variants of Fix_eq for various numbers of arguments, and don't depend on function extensionality. Note that you don't need to change Fix_F, and can instead just prove variants of Fix_eq.
To answer the question you asked, rather than solve your context, the lemma you state is called "forall extensionality".
It is present in Coq.Logic.FunctionalExtensionality, where the axiom of function extensionality is used to prove it. The fact that the standard library version uses an axiom to prove this lemma is, at the very least, strong evidence that it is not provable without axioms in Coq.
Here is a proof sketch of that fact. Since Coq is strongly normalizing*, every proof of x = y in the empty context is judgmentally equal to eq_refl. That is, if you can prove x = y in the empty context, then x and y are convertible. Let f x := inhabited (Vector.t (x + 1)) and let g x := inhabited (Vector.t (1 + x)). It is straightforward to prove forall x, f x = g x by induction on x. Therefore, if your lemma were true without axioms, we could get a proof of
(forall x, inhabited (Vector.t (x + 1))) = (forall x, inhabited (Vector.t (1 + x)))
in the empty context, and hence eq_refl ought to prove this statement. We can easily check and see that eq_refl does not prove this statement. So your lemma ext_fa is not provable without axioms.
Note that equality for functions and equality for types are severely under-specified in Coq. Essentially, the only types (or functions) that you can prove equal in Coq are the ones that are judgmentally equal (or, more precisely, the ones that are expressible as two judgmentally equal lambdas applied to provably-equal closed terms). The only types that you can prove not equal are the ones which are provably not isomorphic. The only functions that you can prove not equal are the ones which provably differ on some concrete element of the domain that you provide. There's a lot of space between the equalities that you can prove, and the inequalities you can prove, and you don't get to say anything about things in this space without axioms.
*Coq isn't actually strongly normalizing because there are some issues with coinductives. But modulo that, it's strongly normalizing.

Related

How does one access the dependent type unification algorithm from Coq's internals -- especially the one from apply and the substitution solution?

TLDR: I want to be able to compare two terms -- one with a hole and the other without the hole -- and extract the actual lambda term that complete the term. Either in Coq or in OCaml or a Coq plugin or in anyway really.
For example, as a toy example say I have the theorem:
Theorem add_easy_0'':
forall n:nat,
0 + n = n.
Proof.
The (lambda term) proof for this is:
fun n : nat => eq_refl : 0 + n = n
if you had a partial proof script say:
Theorem add_easy_0'':
forall n:nat,
0 + n = n.
Proof.
Show Proof.
intros.
Show Proof.
Inspected the proof you would get as your partial lambda proof as:
(fun n : nat => ?Goal)
but in fact you can close the proof and therefore implicitly complete the term with the ddt unification algorithm using apply:
Theorem add_easy_0'':
forall n:nat,
0 + n = n.
Proof.
Show Proof.
intros.
Show Proof.
apply (fun n : nat => eq_refl : 0 + n = n).
Show Proof.
Qed.
This closes the proof but goes not give you the solution for ?Goal -- though obviously Coq must have solved the CIC/ddt/Coq unification problem implicitly and closes the goals. I want to get the substitution solution from apply.
How does one do this from Coq's internals? Ideally while remaining in Coq but OCaml internals or coq plugin solutions or in fact any solution I am happy with.
Appendix 1: how did I realize apply must use some sort of "coq unification"
I knew that apply must be doing this because in the description of the apply tactic I know apply must be using unification due to it saying this:
This tactic applies to any goal. The argument term is a term well-formed in the local context. The tactic apply tries to match the current goal against the conclusion of the type of term. If it succeeds, then the tactic returns as many subgoals as the number of non-dependent premises of the type of term.
This is very very similar to what I once saw in a lecture for unification in Isabelle:
with some notes on what that means:
- You have/know rule [[A1; … ;An]] => A (*)
- that says: that given A1; …; An facts then you can conclude A
- or in backwards reasoning, if you want to conclude A, then you must give a proof of A1; …;An (or know Ai's are true)
- you want to close the proof of [[B1; …; Bm]] => C (**) (since thats your subgoal)
- so you already have the assumptions B1; …; Bm lying around for you, but you wish to be able to conclude C
- Say you want to transform subgoal (**) using rule (*). Then this is what’s going on:
- first you need to see if your subgoal (**) is a "special case" of your rule (*). You commence by checking if the conclusion (targets) of the rules are "equivalent". If the conclusions match then instead of showing C you can now show A instead. But for you to have (or show) A, you now need to show A1; … ;An using the substitution that made C and A match. The reason you need to show A1;...;An is because if you show them you get A automatically according to rule (*) -- which by the "match" (unification) shows the original goal you were after. The main catch is that you need to do this by using the substitution that made A and C match. So:
- first see if you can “match” A and C. The conclusions from both side must match. This matching is called unification and returns a substitution sig that makes the terms equal
- sig = Unify(A,C) s.t. sig(A) = sig(C)
- then because we transformed the subgoal (**) using rule (*), we must then proceed to prove the obligations from the rule (*) we used to match to conclusion of the subgoal (**). from the assumptions of the original subgoal in (**) (since those are still true) but using the substitution sig that makes the rules match.
- so the new subgoals if we match the current subgoal (*) with rule (**) is:
- [[sig(B1); … ; sig(Bm) ]] => sigm(A1)
- ...
- [[sig(B1); … ; sig(Bm) ]] => sigm(An)
- Completing/closing the proof above (i.e. proving it) shows/proves:
- [[sig(B1); …;sig(Bm) ]] => sig(C)
- Command: apply (rule <(*)>) where (*) stands for the rule names
Appendix2: why not exact?
Note that initially I thought exact was the Coq tactic I wanted to intercept but I was wrong I believe. My notes on exact:
- exact p. (assuming p has type U).
- closes a proof if the goal term T (i.e. a Type) matches the type of the given term p.
- succeeds iff T and U are convertible (basically, intuitively if they unify https://coq.inria.fr/refman/language/core/conversion.html#conversion-rules since are saying if T is convertible to U)
conversion seems to be equality check not really unification i.e. it doesn't try to solve a system of symbolic equations.
Appendix 3: Recall unification
brief notes:
- unification https://en.wikipedia.org/wiki/Unification_(computer_science)
- an algorithm that solves a system of equations between symbolic expressions/terms
- i.e. you want
- cons2( cons1( x, y, ...,) ..., cons3(a, b, c), ... ) = cons1(x, nil)
- x = y
- basically a bunch of term LHS term RHS and want to know if you can make them all equal given the terms/values and variables in them...
- term1 = term2, term3 = term4 ? with some variables perhaps.
- the solution is the substitution of the variables that satisfies all the equations
bounty
I'm genuinely curious about intercepting the apply tactic or call its unification algorithm.
apply indeed solve a unification, according to the document.
The tactic apply relies on first-order unification with dependent types unless the conclusion of the type of term is of the form P (t1 ... tn) with P to be instantiated.
Note that generally, the apply will turn one "hole" to several "hole"s that each cooresponds to a subgoal generated by it.
I have no idea how to access the internal progress of apply and get the substitution it uses.
However, You can call unify t u to do unification maully. you can refer to the official document. As far as I am concerned, the unicoq plugin provides another unification algorithm, and you can use munify t u to find unification between two items, see the Unicoq official repo.
An example of using unify and mutify:
From Unicoq Require Import Unicoq.
Theorem add_easy_0'':
forall n:nat,
0 + n = n.
Proof.
Show Proof.
intros.
Show Proof.
refine ?[my_goal].
Show my_goal.
munify (fun t : nat => eq_refl : 0 + t = t) (fun n : nat => ?my_goal).
(* unify (fun t : nat => eq_refl : 0 + t = t) (fun n : nat => ?my_goal). *)
Qed.
However, I wonder whether I have understand your question correctly.
Do you want to name the goal?
If you want to "extract the actual lambda term that complete the (parial) term". The so-called "lamda term" is the goal at that time, isn't it? If so, why to you want to "extract" it? It is just over there! Do you want to store the current subgoal and name it? If so, the abstract tactic perhaps helps, as mentioned in How to save the current goal / subgoal as an `assert` lemma
For example:
Theorem add_easy_0'':
forall n:nat,
0 + n = n.
Proof.
Show Proof.
intros.
Show Proof.
abstract apply eq_refl using my_name.
Check my_name.
(*my_name : forall n : nat, 0 + n = n*)
Show Proof.
(*(fun n : nat => my_name n)*)
Qed.
Do you want to get the substituion?
Are you asking a substituion that make the goal term and the conclusion of the theorem applied match? For example:
Require Import Arith.
Lemma example4 : 3 <= 3.
Proof.
Show Proof.
Check le_n.
(* le_n : forall n : nat, n <= n *)
apply le_n.
Are you looking forward to get something like n=3? If you want to get such a "substitution", I am afraid the two tactics mentioned above will not help. Writing OCaml codes should be needed.
Do you want store the prove of current goal?
Or are you looking forward to store the proof of the current goal? Perhaps you can try assert, as mentioned in Using a proven subgoal in another subgoal in Coq.

Decidable equality statement with Set vs. Prop

When looking at results for types with decidable equality (especially in Eqdep_dec) there are some of the results that (for a type A) require
forall x y : A, x = y \/ x <> y
whereas some require
forall x y : A, {x = y} + {x <> y}
It is my impression that it is the last one that is referred to as decidable equality, but I am very much uncertain what the difference is. I know that x = y \/ x <> y in Prop and {x = y} + {x <> y} is in Set, and I can prove the first one from the second one but not the other way around. As far as I understand it, it is because I am not allowed to construct values of type Prop from values of type Set.
Can anyone tell what the difference between the two are? Are there some example of a type for which the first statement can be proved but not the second. Also, is it true that the version with {x = y} + {x <> y} is what is referred to as decidable equality?
You are correct that the latter definition, the one which lives in Set, is referred to as decidable equality.
Intuitively, we interpret objects in Set as programs, and objects in Prop as proofs. So the decidable equality type is the type of a function which takes any two elements of some type A and decides whether they are equal or unequal.
The other statement is slightly weaker. It describes the proposition that any two elements of A are either equal of unequal. Notably, we would not be able to inspect which outcome is the case for specific values of x and y, at least outside of case analysis within a proof. This is the result of the Prop elimination restriction that you alluded to (although you got it backwards: one is not allowed to construct values of sort Set/Type by eliminating/matching on an element of sort Prop).
Without adding axioms, the Prop universe is constructive, so I believe that there would not be any types A such that equality is undecidable but the propositional variant is provable. However, consider the scenario in which we make the Prop universe classical by adding the following axiom:
Axiom classic : forall P, P \/ ~P
This would make the propositional variant trivially provable for any type A, while the decidable equality may not be realizable.
Note that our axiom is a proposition. Intuitively, it makes sense that either a proposition or its negation must hold. If we hadn't made this a Prop (for example, if we axiomatized forall P, {P} + {~P}), then we would likely not accept the axiom, since it would instead be declaring the existence of a universal decision procedure.
That was a bit of a digression, but hopefully it demonstrated some differences in our interpretation of Props and Sets.

Not explicitly specifying instances of a type in coq

I'm interested in trying my hand at constructing set theory using Coq. I would like to define a type sets without specifying what its members are, and a function mapping two sets to a Prop
Definition elem (s1 s1 : sets) : Prop.
I would then make the axioms of set theory hypotheses, and express theorems as (for example)
Theorem : ZFC -> (forall s : sets, ~ elem s s).
However, the syntax above doesn't work. Is this idea something that can be done in Coq? Is there a better way to accomplish this goal in Coq? I am very new to Coq, so I apologize if there is an obvious way of doing this that I don't know.
You need to give names to theorems. And for postulating things, use Parameter and Axiom (which technically mean the same thing but you can use to informally distinguish between concepts and facts).
Parameter set : Type.
Parameter elem : set -> set -> Prop.
Axiom set_extensionality : forall x y, (forall z, elem z x <-> elem z y) -> x = y.
(* etc. *)
In comparison, Definition and Theorem are used for defining and proving things. Having postulated the ZFC axioms, you can prove that a set is not an element of itself. The Theorem command takes a theorem name first (used to refer to it in the future):
Theorem no_self_elem : forall x, ~ elem x x.
Proof.
(* tactics here. *)
Qed.

How to perform induction over two inductive predicates?

I am starting with Coq and trying to formalize Automated Amortised Analysis. I am at lemma 4.13:
Lemma preservation : forall (Sigma : prog_sig) (Gamma : context) (p : program)
(s : stack) (h h' : heap) (e : expr) (c : type0) (v : val),
(* 4.1 *) has_type Sigma Gamma e c ->
(* 4.2 *) eval p s h e v h' ->
(* 4.3 *) mem_consistant_stack h s Gamma ->
(* 4.a *) mem_consistant h' v c /\ (* 4.b *) mem_consistant_stack h' s Gamma.
Proof.
intros Sigma Gamma p s h h' e c v WELL_TYPED EVAL.
The manual proof uses a double induction:
Proof. Note that claim (4.b) follows directly by Lemma 4.8 and Lemma
4.12. Each location l ∈ dom( H ) is either left unaltered or is overwritten by the value Bad and hence does not invalidate memory
consistency.
However, the first claim (4.a) requires a proof by
induction on the lengths of the derivations of (4.2) and (4.1) ordered
lexicographically with the derivation of the evaluation taking
priority over the typing derivation. This is required since an in-
duction on the length of the typing derivation alone would fail for
the case of function application: in order to allow recursive
functions, the type rule for application is a terminal rule relying on
the type given for the function in the program’s signature. However,
proving this case requires induction on the statement that the body of
the function is well-typed, which is most certainly a type derivation
of a longer length (i.e. longer than one step), prohibiting us from
using the induction hypothesis. Note in this particular case that the
length of the derivation for the evaluation statement does decrease.
An induction over the length of the derivation for premise (4.2) alone
fails similarly. Consider the last step in the derivation of premise
(4.1) being derived by the application of a structural rule, then the
length of the derivation for (4.2) remains exactly the same, while the
length of the derivation for premise (4.1) does decrease by one step.
Using induction on the lexicographically ordered lengths of the type
and evaluation derivations allows us to use the induction hypothesis
if either the length of the deriva- tion for premise (4.2) is
shortened or if the length of the derivation for premise (4.2) remains
unchanged while the length of the typing derivation is reduced. We
first treat the cases where the last step in the typing derivation was
obtained by application of a structural rule, which are all the cases
which leave the length of the derivation for the evaluation unchanged.
We then continue to consider the remaining cases based
604.3 Operational Semantics on the evaluation rule that had been applied last to derive premise (4.2), since the remaining type rules
are all syntax directed and thus unambiguously determined by the
applied evaluation rule.
How can such a "double induction" be performed in Coq?
I tried induction EVAL; induction WELL_TYPED, but got 418 subgoals, most of wich are unprovable.
I also tried to start with induction EVAL and use induction WELL_TYPED later, but go stucked in a similar situation.
I agree with #jbapple that a minimal example is better. That said, it may be that you are simply missing a concept of length of derivation. Note that the usual concept of proof by induction over a predicate actually implements something that is close to induction over the height of derivations, but not quite.
I propose that you exhibit two new predicates eval_n and
has_type_n that each express the same as eval
and has_type, but with an extra argument with meaning "... and derivation has size n". There are several ways in which size might be defined but I suspect that height will be enough for you.
Then you can prove
eval a1 .. ak <-> exists n, eval_n a1 .. ak n
and
has_type a1 .. ak <-> exists n, has_type a1 .. ak n
You should then be able to prove
forall p : nat * nat, forall a1 ... ak, eval_n a1 .. ak (fst p) ->
has_type_n a1 .. ak (snd p) -> YOUR GOAL
by well founded induction on pairs of natural numbers, using the lexical order construction of library Wellfounded (I suggest library Lexicographic_Product.v, it is a bit of an overkill for just pairs of natural numbers, but you only need to find the right instantiation).
This will be unwieldy because induction hypotheses will only refer to pairs
of numbers that are comparable for the lexical order, and you will have to perform inversions on the hypotheses concerning eval_n and has_type_n, but that should go through.
There probably exists a simpler solution, but for lack of more information from your side, I can only propose the big gun.

Definition by property in coq

I am having trouble with formalizing definitions of the following form: define an integer such that some property holds.
Let's say that I formalized the definition of the property:
Definition IsGood (x : Z) : Prop := ...
Now I need a definition of the form:
Definition Good : Z := ...
assuming that I proved that an integer with the property exists and is unique:
Lemma Lemma_GoodExistsUnique : exists! (x : Z), IsGood x.
Is there an easy way of defining Good using IsGood and Lemma_GoodExistsUnique?
Since, the property is defined on integer numbers, it seems that no additional axioms should be necessary. In any event, I don't see how adding something like the axiom of choice can help with the definition.
Also, I am having trouble with formalizing definitions of the following form (I suspect this is related to the problem I described above, but please indicate if that is not the case): for every x, there exists y, and these y are different for different x. Like, for example, how to define that there are N distinct good integer numbers using IsGood:
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) := ...?
In real-world mathematics, definitions like that occur every now and again, so this should not be difficult to formalize if Coq is intended to be suitable for practical mathematics.
The short answer to your first question is: in general, it is not possible, but in your particular case, yes.
In Coq's theory, propositions (i.e., Props) and their proofs have a very special status. In particular, it is in general not possible to write a choice operator that extracts the witness of an existence proof. This is done to make the theory compatible with certain axioms and principles, such as proof irrelevance, which says that all proofs of a given proposition are equal to each other. If you want to be able to do this, you need to add this choice operator as an additional axiom to your theory, as in the standard library.
However, in certain particular cases, it is possible to extract a witness out of an abstract existence proof without recurring to any additional axioms. In particular, it is possible to do this for countable types (such as Z) when the property in question is decidable. You can for instance use the choiceType interface in the Ssreflect library to get exactly what you want (look for the xchoose function).
That being said, I would usually advice against doing things in this style, because it leads to unnecessary complexity. It is probably easier to define Good directly, without resorting to the existence proof, and then prove separately that Good has the sought property.
Definition Good : Z := (* ... *)
Definition IsGood (z : Z) : Prop := (* ... *)
Lemma GoodIsGood : IsGood Good.
Proof. (* ... *) Qed.
Lemma GoodUnique : forall z : Z, IsGood z -> z = Good.
If you absolutely want to define Good with an existence proof, you can also change the proof of Lemma_GoodExistsUnique to use a connective in Type instead of Prop, since it allows you to extract the witness directly using the proj1_sig function:
Lemma Lemma_GoodExistsUnique : {z : Z | Good z /\ forall z', Good z' -> z' = z}.
Proof. (* ... *) Qed.
As for your second question, yes, it is a bit related to the first point. Once again, I would recommend that you write down a function y_from_x with type Z -> Z that will compute y given x, and then prove separately that this function relates inputs and outputs in a particular way. Then, you can say that the ys are different for different xs by proving that y_from_x is injective.
On the other hand, I'm not sure how your last example relates to this second question. If I understand what you want to do correctly, you can write something like
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) :=
exists zs : list Z,
Z.of_nat (length zs) = N
/\ NoDup zs
/\ Forall IsGood zs.
Here, Z.of_nat : nat -> Z is the canonical injection from naturals to integers, NoDup is a predicate asserting that a list doesn't contain repeated elements, and Forall is a higher-order predicate asserting that a given predicate (in this case, IsGood) holds of all elements of a list.
As a final note, I would advice against using Z for things that can only involve natural numbers. In your example, your using an integer to talk about the cardinality of a set, and this number is always a natural number.