Why is sum-type a disjunction in the Curry-Howard correspondence? - category-theory

According to the Curry-Howard correspondence the sum-type aka tagged-union is the equivalent of disjunction, logical OR
Why is this the case? Is it not closer to XOR? (a or b) implies that it could be a or b or both, whereas Either a b must be a or b but never both.

Curry-Howard correspondence says that an element of Either a b represents a proof of a or b. To prove a disjunction it's enough to prove (provide an element of) a or b. You do this by constructing Either a b using either Left a or Right b.

Related

Can I safely assume that isomorphic types are equal?

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.

Extensionality axiom: why is it not unsound

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.

Proof that equality is symmetric in Coq

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.

Unable to formulate a prover9 axiom

I'm trying to teach basic set theory to Prover9. The following definition of membership seems to work very well (the second axiom is just to make lists unordered):
member(x,[x:y]).
[x,y]=[y,x].
With this, I can have Prover9 prove 'complicated' things like member([A,B],[C,[A,B]]) and others.
However, I must be doing something wrong when I use it to define subsets:
subset(x,y) <-> (member(z,x) -> member(z,y)).
Prover9 clausifies this as subset(x,y) | -member(z,y) and uses it to prove false clauses, like subset([A],[B,C]).
What am I missing?
Your "second axiom ... just to make lists unordered" looks suspicious.
Note [x,y] is a two-element list. So your axiom is saying nothing about lists in general. Your 'complicated' examples, are still 2-element lists. So not very complicated. I think you'll be unable to prove member(A, [C, B, A])
Contrast that [x:y] in your first axiom is a 1-or-more-element list. The y might be nil, or might be any number of elements. IOW y is a list, whereas in [x,y], y is an element of a list.
See http://www.cs.unm.edu/~mccune/prover9/manual/2009-11A/, 'Clauses & Formulas' at 'list notation'.
I'd go:
member(x, [x:y]).
member(x, z) -> member(x, [y:z]).
(But that defines a bag, not a set.)
I think the quantification over variables is a red herring.
Edit: Errk. I'm wrong. So I don't know why I got this result:
The example that #Doug points to doesn't need to quant z 'inside'
the rhs of equivalence. You can just remove all the explicit
quantification, and the proof still works.
OK. Let's apply the rewrite rules per the Manual 'Clauses & Formulas' at "If non-clausal formulas are entered ...".
That definition of subset is an equivalence (aka bi-implication); rewrite as two separate axioms: 'forwards' and backwards' implications; rewrite each of those using p -> q ==> -p | q.
In the 'forwards' direction we get:
-subset(x, y) | (member(z, x) -> member(z, y)).
Doesn't matter whether the z is quantified narrow or wide.
In the 'backwards' direction:
-(member(z, x) -> member(z, y)) | subset(x, y).
Here if we quantify z narrowly around the implication, that's inside the scope of negation; and so different to quantifying across the whole formula.
Conclusion: both your definition of member( ) and of subset( ) are wrong.
BTW Are you sure you need to define member? The proof #Doug points to just takes member(x,y) as primitive.

What forms of goal in Coq are considered to be "true"?

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