I have a set as a parameter:
Parameter Q:Set.
Now I want to define another parameter that is a subset of Q. Something like:
Parameter F: subset Q.
How I can define that? I guess I can add the restriction later as an axiom, but seems more natural to express it directly in the type of F.
You can't express it directly.
It's misleading to think of objects in Set as mathematical sets. Set is the sort of datatypes, the same kinds of types that you find in programming languages (except that Coq's types are very powerful).
Coq doesn't have subtyping¹. If the two types F and Q are distinct, then they are disjoint, as far as the mathematical model is concerned.
The usual approach is to declare F as a completely related set, and declare a canonical injection from F to Q. You'll want to specify any interesting property of that injection, beyond the obvious.
Parameter Q : Set.
Parameter F : Set.
Parameter inj_F_Q : F -> Q.
Axiom inj_F_Q_inj : forall x y : F, inj_F_Q x = inj_F_Q y -> x = y.
Coercion inj_F_Q : F >-> Q.
That last line declares a coercion from F to Q. That lets you put an object of type F wherever the context requires the type Q. The type inference engine will insert a call to inj_F_Q. You will need to write the coercion explicitly occasionally, since the type inference engine, while very good, is not perfect (perfection would be mathematically impossible). There is a chapter on coercions in the Coq reference manual; you should at least skim through it.
Another approach is to define your subset with an extensional property, i.e. declare a predicate P on the set (the type) Q and define F from P.
Parameter Q : Set.
Parameter P : Q -> Prop.
Definition G := sig P.
Definition inj_G_Q : G -> Q := #proj1_sig Q P.
Coercion inj_G_Q : G >-> Q.
sig is a specification, i.e. a weak sum type, i.e. a pair consisting of an object and a proof that said object has a certain property. sig P is eta-equivalent to {x | P x} (which is syntactic sugar sig (fun x => P x)). You have to decide whether you prefer the short or the long form (you need to be consistent). The Program vernacular is often useful when working with weak sums.
¹
There is subtyping in the module language, but that's not relevant here. And coercions fake subtyping well enough for many uses, but they're not the real thing.
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.
I have a type BoundedNat n, representing natural numbers smaller than n. My current implementation is as follows:
Definition BoundedNat n := {x : nat | x < n}.
Manipulating elements of type BoundedNat n is relatively heavyweight. I constantly need to wrap (using exist n ltac:(lia)) and unwrap (using proj1_sig) elements. How can I best piggyback off the underlying type's notations, equality, ordering, etc.?
Though you can definitely roll up your own implementation of bounded natural numbers, I strongly encourage you to reuse an existing one. My favorite library for that is ssreflect. It contains an ordinal n type family that corresponds to your BoundedNat, defined in fintype.v (doc here). There is a coercion from ordinal to nat so that you can readily reuse most operators on natural numbers transparently -- e.g. you can write i < j directly when i j : ordinal n.
Building terms of ordinal is more complicated, since it requires the proof argument. There is no best way of finding this proof, so the way to proceed depends on the application. For instance, adding a constant to a bounded nat is common enough to deserve a specialized operation in ssreflect:
rshift : forall m n, ordinal n -> ordinal (m + n)
One of the advantages of using ssreflect is that it comes with generic support for subset types like ordinal. For instance, there is a insub : nat -> option (ordinal n) function that succeeds if an only if its argument is bounded by n. This function works not only for nat and ordinal, but for any pair of types connected by the subtype interface: sT is a subtype of T if it is of the form {x : T | P x} for some boolean predicate P. Thus, you can manipulate subtypes with a consistent interface rather than rolling up your own each time.
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.
Can we assign cardinals in Coq to Prop, Set and each Type_i ? I only see the definition of finite cardinals in Coq's library, so maybe we need that of big cardinals to begin with.
According to the proof-irrelevance semantics, for example exposed here, Set and the Type_i form an increasing sequence of inaccessible cardinals. Can this be proven in Coq ?
Prop seems more complex because of impredicativity. Proof-irrelevance means we identify all proofs of the same P : Prop, and interpret Prop itself as the pair {false, true}. So the cardinal of Prop would be 2. However, for any two proofs p1 p2 : P, Coq does not accept eq_refl p1 as a proof of p1 = p2. So Coq does not completely identify p1 and p2. And on the other hand, impredicativity means that for any A : Type and P : Prop, A -> P is of type Prop. That makes a lot more inhabitants than in Set.
If this is too hard, can Coq prove that Prop and Set are uncountable ? By Cantor's theorem, Coq easily proves that there is not surjection nat -> (nat -> Prop). This does not seem very far from proving there is not surjection nat -> Prop. But then we need the filter Prop -> (nat -> Prop), that isolates which Prop's have a free nat variable. Can we define this filter in Coq, since we cannot pattern-match on Prop ?
It is not possible to show that Prop is uncountable inside Coq. The ClassicalFacts module in the standard library shows that the axiom of propositional degeneracy, forall A : Prop, A = True \/ A = False, is equivalent to the presence of the excluded middle and propositional extensionality. Since Coq's set theoretic model validates these two axioms, Coq cannot refute degeneracy.
It is certainly possible to show that Set and Type are infinite, since they contain all types Fin n of natural numbers bounded by n, and these types are provably different from one another since they have different cardinality. I suspect that it is possible to show that they are uncountable by adapting the usual diagonalization argument -- that is, assume that some invertible count function e : nat -> Set, and try to encode something like the type of all natural numbers that "do not contain themselves". I do not know how you would go about proving that these types are inaccessible cardinals.
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