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.
Related
I am trying to understand the apparent paradox of the logical framework of theorem provers like Coq not including LEM yet also being able to construct proofs by contradiction. Specifically the intuitionistic type theory that these theorem provers are based on does not allow for any logical construction of the form ¬(¬P)⇒P, and so what is required in order to artificially construct this in a language like Coq? And how is the constructive character of the system preserved if this is allowed?
I think you are mixing up two related uses of contradiction in logic. One is the technique of proof by contradiction, which says that you can prove P by proving ~ (~ P) -- that is, by showing that ~ P entails a contradiction. This technique is actually not available in general in constructive logics like Coq, unless one of the following applies.
You add the excluded middle forall P, P \/ ~ P as an axiom. Coq supports this, but this addition means that you are not working in a constructive logic anymore.
The proposition P is known to be decidable (i.e., P \/ ~ P holds). This is the case, for example, for the equality of two natural numbers n and m, which we can prove by induction.
The proposition P is of the form ~ Q. Since Q -> ~ (~ Q) holds constructively, by the law of contrapositives (which is also valid constructively), we obtain ~ (~ (~ Q)) -> (~ Q).
The other use of contradiction is the principle of explosion, which says that anything follows once you assume a contradiction (i.e., False in Coq). Unlike proof by contradiction, the principle of explosion is always valid in constructive logic, so there is no paradox here.
In constructive logic, by definition, a contradiction is an inhabitant of the empty type 0, and, also by definition, the negation ¬P of a proposition P is a function of type: P -> 0 that gives an inhabitant of the empty type 0 from an inhabitant (a proof) of P.
If you assume an inhabitant (proof) of P, and derive constructively an inhabitant of 0, you have defined a function inhabiting the type P -> 0, i.e. a proof of ¬P. This is a constructive sort of proof by contradiction: assume P, derive a contradiction, conclude ¬P.
Now if you assume ¬P and derive a contradiction, you have a constructive proof of ¬¬P, but cannot conclude constructively that you have a proof of P: for this you need the LEM axiom.
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.
Let A and B be Types, and f : A -> B and g : B -> A be functions inverse to each other. In other words A and B are isomorphic types.
Is it true that one cannot prove that A <> B?
Can I safely add the axiom that A = B?
Is this axiom compatible with the other axioms of the standard library of Coq? And, if yes, why isn't it in the standard library?
These kind of questions are the domain of predilection of homotopy type theory but here is a tentative synthetic answer to your questions.
In CIC (± the ideal theory underlying Coq), we say that two types A and B are equivalent if there is a function f : A -> B with left inverse g : B -> A (that is f o g = id_B) and right inverse h : B -> A (that is h o f = id_B).
You can use an isomorphism from A to B to show that they are equivalent.
Homotopy type theory is concerned with the addition of an axiom to CIC (or rather MLTT) called univalence that roughly states that equivalence between types and equality coincide (to be more precise, there is a map id_to_equiv : A = B -> equiv A B and univalence says that this map is itself an equivalence).
Univalence is compatible with CIC in the sense that there exist models of CIC that validate this axiom.
So to answer your questions:
Yes, one cannot prove A <> B in CIC because any such proof would contradict univalence (hence no model of CIC + univalence could exist)
You won't be able to prove False since it is a special case of univalence that does have models, however the computational content of Coq will be partially lost (as it is always the case with the addition of any axiom).
Univalence is compatible with some axioms of the standard library of Coq (excluded-middle for instance) but not with others (Uniqueness of identity proofs, a.k.a. UIP, univalence states that there are 2 proofs of Bool = Bool). Concerning the absence of univalence from the standard library, it stems from the fact that the standard library defines equality in Prop, which is incompatible with the existence of multiple witnesses of identity. However the axiom that you mention might be formulated in a way that's compatible with UIP (there have been some work by Bauer and Winterhalter on a so called cardinal model of type theory). Whether it is compatible with the other axioms from the standard library would have to be checked.
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.
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