When I prove some theorem, my goal evolves as I apply more and more tactics. Generally speaking the goal tends to split into sub goals, where the subgoals are more simple. At some final point Coq decides that the goal is proven. How this "proven" goal may look like? These goals seems to be fine:
a = a. (* Any object is identical to itself (?) *)
myFunc x y = myFunc x y. (* Result of the same function with the same params
is always the same (?) *)
What else can be here or can it be that examples are fundamentally wrong?
In other words, when I finally apply reflexivity, Coq just says ** Got it ** without any explanation. Is there any way to get more details on what it actually did or why it decided that the goal is proven?
You're actually facing a very general notion that seems not so general because Coq has some user-friendly facility for reasoning with equality in particular.
In general, Coq accepts a goal as solved as soon as it receives a term whose type is the type of the goal: it has been convinced the proposition is true because it has been convinced the type that this proposition describes is inhabited, and what convinced it is the actual witness you helped build along your proof.
For the particular case of inductive datatypes, the two ways you are going to be able to proved the proposition P a b c are:
by constructing a term of type P a b c, using the constructors of the inductive type P, and providing all the necessary arguments.
or by reusing an existing proof or an axiom in the environment whose type you can get to match P a b c.
For the even more particular case of equality proofs (equality is just an inductive datatype in Coq), the same two ways I list above degenerate to this:
the only constructor of equality is eq_refl, and to apply it you need to show that the two sides are judgementally equal. For most purposes, this corresponds to goals that look like T a b c = T a b c, but it is actually a slightly more broad notion of equality (see below). For these, all you have to do is apply the eq_refl constructor. In a nutshell, that is what reflexivity does!
the second case consists in proving that the equality holds because you have other equalities in your context, nothing special here.
Now one part of your question was: when does Coq accept that two sides of an equality are equal by reflexivity?
If I am not mistaken, the answer is when the two sides of the equality are αβδιζ-convertible.
What this grossly means is that there is a way to make them syntactically equal by repeated applications of:
α : sane renaming of non-free variables
β : computing reducible expressions
δ : unfolding definitions
ι : simplifying matches
ζ : expanding let-bound expressions
[someone please correct me if more rules apply or if I got one wrong]
For instance some of the things that are not captured by these rules are:
equality of functions that do more or less the same thing in different ways:
(fun x => 0 + x) = (fun x => x + 0)
quicksort = mergesort
equality of terms that are stuck reducing but would be equal:
forall n, 0 + n = n + 0
Related
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.
Axiom of extensionality says that two functions are equal if their actions on each argument of the domain are equal.
Axiom func_ext_dep : forall (A : Type) (B : A -> Type) (f g : forall x, B x),
(forall x, f x = g x) -> f = g.
Equality = on both side of the theorem statement is propositional equality (a datatype with a single eq_refl constructor).
Using this axiom it could be proven that f = a + b and g = b + a are propositionally equal.
But f and g are obviously not equal as data structures.
Could you please explain what I'm missing here?
Probably that function objects don't have normal form?
EDIT: After further discussion in the comments, the actual point of confusion was this:
Doesn't match a with... = match b with gives me False right away the same way as S S Z = S Z does?
You can pattern-match on nat, you can't on functions. Dependent pattern-matching is how we can prove injectivity and disjointness of constructors, whereas the only thing we can do with a function is to apply it. (See also How do we know all Coq constructors are injective and disjoint?)
Nevertheless, I hope the rest of the answer below is still instructive.
From the comments:
AFAIU, = has a very precise meaning in Coq/CIC - syntactic equality of normal forms.
That's not right. For example we can prove the following:
Lemma and_comm : forall a b : bool, (* a && b = b && a *)
match a with
| true => b
| false => false
end = match b with
| true => a
| false => false
end.
Proof.
destruct a, b; reflexivity.
Qed.
We can only use eq_refl when the two sides are syntactically equal, but there are more reasoning rules we can apply beyond the constructors of an inductive propositions, most notably dependent pattern-matching, and, if we admit it, functional extensionality.
But f and g are obviously not equal as data structures.
This statement seems to confuse provability and truth. It's important to distinguish these two worlds. (And I'm not a logician, so take what I'm going to say with a grain of salt.)
Coq is a symbol-pushing game, with well-defined rules to construct terms of certain types. This is provability. When Coq accepts a proof, all we know is that we constructed a term following the rules.
Of course, we also want those terms and types to mean something. When we prove a proposition, we expect that to tell us something about the state of the world. This is truth. And in a way, Coq has very little say in the matter. When we read f = g, we are giving a meaning to the symbol f, a meaning to g, and also a meaning to =. This is entirely up to us (well, there are always rules to follow), and there's more than one interpretation (or "model").
The "naive model" that most people have in mind views functions as relations (also called graphs) between inputs and outputs. In this model, functional extensionality holds: a function is no more than a mapping between inputs and outputs, so two functions with the same mappings are equal. Functional extensionality is sound in Coq (we can't prove False) because there is at least one model where it is valid.
In the model you have, a function is characterized by its code, modulo some equations. (This is more or less the "syntactic model", where we interpret every expression as itself, with the minimal possible amount of semantic behavior.) Then, indeed there are functions that are extensionally equal, but with different code. So functional extentionality is not valid in this model, but that doesn't mean it's false (i.e., that we can prove its negation) in Coq, as justified previously.
f and g are not "obviously not equal", because equality, like everything else, is relative to a particular interpretation.
I am just starting with Coq and right now trying to prove some stuff that is in "The Little Prover".
One of the theorems I came across is the following:
Theorem equal_swap : forall (A: Type) (x:A) (y:A),
(x = y) = (y = x).
However, I am unable to prove this. I tried finding out how to rewrite the right side of the equation with eq_sym, but I am unable to apply it to only one expression of the goal.
How would I go about proving this theorem?
One thing that Coq uses pervasively is the concept of "propositions as types". Intuitively, types are collections of objects. So what are the elements of these collections? They are proofs. A proposition that is provable is a type that contains an element, a proposition that is not provable is a type that does not contain a proof.
So a = b is a type, a type of proofs and b = a is also a type of proofs but they don't prove the same statement. The purpose of the logic in Coq is to be very precise about statements. Can we say that a = b and b = a are the same? Well, in a sense they are not. If I have a goal of the form C(a, b) and I rewrite with a proof of a = b then I obtain C(a, a) and if I rewrite with a proof of b = a then I obtain C(b, b) and these two don't look the same. One make argue that they are the same (because a and b are the same by assumption) but one may also argue that they are not the same (because you don't use them in the same manner).
When designing a logical system like Coq, it turns out that you can do a lot of logic even if you don't try to talk about equality between propositions, but concentrate yourself on just using equivalence between propositions. So people tried to add the least amount of properties to the concept of equality. In particular, equality between types was left naked. You will see that equality is practical to use when talking about equality between first-order data, it is less convenient when talking about higher-order data (like equality between functions), and it is awkward when talking about equality between types.
On the other hand, if they want to study the relation between two propositions, they only try to check whether one proposition implies another one, and if they want to be more precise, they try to see if they imply each other mutually. For most practical purposes this will be enough, and I suggest you stick to this discipline as long as you consider yourself a beginner.
Here, we may want to prove a = b -> b = a. If we do this as a proof using tactics, then intro will help us give a name to a = b (say H) and rewrite H will help us transform b = a into a = a. Now the last proof can be done by reflexivity. But when I say transform b = a into a = a. I only mean that a = a -> b = a has a proof, in other words "there is a function, when given as input a proof of a = a, it produces as output a proof of b = a. When performing a proof, we have the impression that the proof of a = a is transformed into a proof of b = a while staying the same, but it is not: two different proofs are observed here.
In the end, (a = b) <-> (b = a) is just the conjunction of (a = b) -> (b = a) and (b = a) -> (a = b). The rewrite tactic has also been extended so that you can also rewrite with a theorem is an equivalence, instead of an equality.
In the Coq standard library, there is an enumerated type called comparison with three elements Eq,Lt,Gt. This is used to define the less-than or less-than-or-equal operators in ZArith: m < n is defined as m ?= n = Lt and m <= n is defined as m ?= n <> Gt. By virtue of Hedberg's theorem (UIP_dec in the standard library) I can prove that < is proof-irrelevant, but I run into issues when it comes to <=, since it is defined negatively. I find this particularly annoying, since if <= were defined in the, IMO, more natural way (m ?= n = Lt \/ m ?= n = Eq) I would be able to prove proof-irrelevance just fine.
Context: I'm using some previously written Coq files where the author uses proof irrelevance as a global axiom to avoid bringing in setoids, and for aesthetic reasons I would prefer to do without axioms. It seems then to me that my options are:
Hope that ultimately Z.le as currently defined is still proof-irrelevant
Use my own definition(s) so that proof irrelevance is provable (less satisfying since I'd like to stick to the standard library as much as possible)
Rework things with setoids
No, this is not provable in Coq. It depends on the axiom of function extensionality, which says that (forall x, f x = g x) -> f = g. It's quite easy to prove that all negations are proof irrelevant under this assumption (since False is proof irrelevant), and quite impossible to prove that any negations are proof irrelevant without it.
Assume that I need to prove something like the following:
x: nat
(fun _ : nat => 0) = (fun y : nat => if beq_nat x y then 0 else 0)
Since y is not in the environment, it looks like I can't destruct on beq_nat x y to simplify the right-hand side. Is there a simple way to simplify expressions within an anonymous function?
Besides being able to massage two functions to look equal, is there a way to deduce that two functions are the same by showing that they produce the same value on all inputs?
EDIT: I realize that I might be asking for the impossible, since those functions are not the same, it's just that when applied to an argument they produce the same value. I'm not sure exactly how Coq interprets this.
I believe this is a case of what is referred to as functional extensionality, where you want to prove that two functions are extensionally equal (they behave the same from the caller's point of view).
You cannot prove it directly in Coq (since = is a definitioinal equality, it is not true), but if you wish to, you can require this module:
http://coq.inria.fr/stdlib/Coq.Logic.FunctionalExtensionality.html
which will provide you with axioms for functional extensionality. You can call the tactic extensionality y. which will give you access to the y.