how to figure out what "=" means in different types in coq - coq

Given a type (like List) in Coq, how do I figure out what the equality symbol "=" mean in that type? What commands should I type to figure out the definition?

The equality symbol is just special infix syntax for the eq predicate. Perhaps surprisingly, it is defined the same way for every type, and we can even ask Coq to print it for us:
Print eq.
(* Answer: *)
Inductive eq (A : Type) (x : A) : Prop :=
| eq_refl : eq x x.
This definition is so minimal that it might be hard to understand what is going on. Roughly speaking, it says that the most basic way to show that two expressions are equal is by reflexivity -- that is, when they are exactly the same. For instance, we can use eq_refl to prove that 5 = 5 or [4] = [4]:
Check eq_refl : 5 = 5.
Check eq_refl : [4] = [4].
There is more to this definition than meets the eye. First, Coq considers any two expressions that are equalivalent up to simplification to be equal. In these cases, we can use eq_refl to show that they are equal as well. For instance:
Check eq_refl : 2 + 2 = 4.
This works because Coq knows the definition of addition on the natural numbers and is able to mechanically simplify the expression 2 + 2 until it arrives at 4.
Furthermore, the above definition tells us how to use an equality to prove other facts. Because of the way inductive types work in Coq, we can show the following result:
eq_elim :
forall (A : Type) (x y : A),
x = y ->
forall (P : A -> Prop), P x -> P y
Paraphrasing, when two things are equal, any fact that holds of the first one also holds of the second one. This principle is roughly what Coq uses under the hood when you invoke the rewrite tactic.
Finally, equality interacts with other types in interesting ways. You asked what the definition of equality for list was. We can show that the following lemmas are valid:
forall A (x1 x2 : A) (l1 l2 : list A),
x1 :: l1 = x2 :: l2 -> x1 = x2 /\ l1 = l2
forall A (x : A) (l : list A),
x :: l <> nil.
In words:
if two nonempty lists are equal, then their heads and tails are equal;
a nonempty list is different from nil.
More generally, if T is an inductive type, we can show that:
if two expressions starting with the same constructor are equal, then their arguments are equal (that is, constructors are injective); and
two expressions starting with different constructors are always different (that is, different constructors are disjoint).
These facts are not, strictly speaking, part of the definition of equality, but rather consequences of the way inductive types work in Coq. Unfortunately, it doesn't work as well for other kinds of types in Coq; in particular, the notion of equality for functions in Coq is not very useful, unless you are willing to add extra axioms into the theory.

Related

Characteristic function of a union

In a constructive setting such as Coq's, I expect the proof of a disjunction A \/ B to be either a proof of A, or a proof of B. If I reformulate this on subsets of a type X, it says that if I have a proof that x is in A union B, then I either have a proof that x is in A, or a proof that x is in B. So I want to define the characteristic function of a union by case analysis,
Definition characteristicUnion (X : Type) (A B : X -> Prop)
(x : X) (un : A x \/ B x) : nat.
It will be equal to 1 when x is in A, and to 0 when x is in B. However Coq does not let me destruct un, because "Case analysis on sort Set is not allowed for inductive definition or".
Is there another way in Coq to model subsets of type X, that would allow me to construct those characteristic functions on unions ? I do not need to extract programs, so I guess simply disabling the previous error on case analysis would work for me.
Mind that I do not want to model subsets as A : X -> bool. That would be unecessarily stronger : I do not need laws of excluded middle such as "either x is in A or x is not in A".
As pointed out by #András Kovács, Coq prevents you from "extracting" computationally relevant information from types in Prop in order to allow some more advanced features to be used. There has been a lot of research on this topic, including recently Univalent Foundations / HoTT, but that would go beyond the scope of this question.
In your case you want indeed to use the type { A } + { B } which will allow you to do what you want.
I think the union of subsets should be a subset as well. We can do this by defining union as pointwise disjunction:
Definition subset (X : Type) : Type := X -> Prop.
Definition union {X : Type}(A B : subset X) : subset X := fun x => A x \/ B x.

Proof that two isomorphic types are different

Given these two types,
Inductive unit : Set := tt.
Inductive otherUnit : Set := ttt.
Can Coq prove they are different, ie unit <> otherUnit ?
Both are singleton types in sort Set so it is not easy to find a Set -> Prop that differentiates them. For example, this does not even type check
Definition singletonTT (A : Set) : Prop := forall x : A, x = tt.
because tt has type unit instead of A.
It's actually admissible in Coq that these two types are equal; that is, you can neither prove they are equal or different, and it's consistent to assume either.
You can't express singletonTT in terms of tt because as you point out, it only type checks for the unit type. Instead you need to treat A opaquely; for example, you can express the property of being a singleton as A /\ forall (x y:A), x = y. Of course, both types are singletons so this doesn't distinguish them.
If you do assume Axiom unit_otherUnit : unit = otherUnit, then you can express something like singletonTT by casting tt to otherUnit: eq_rec _ (fun S => S) tt otherUnit ax = ttt.
When types have different cardinalities (which means they aren't isomorphic) you can use their cardinality to distinguish them and prove the types are distinct. Easy examples include False <> True and unit <> bool, and a more complicated example is nat <> (nat -> nat).

Proving equality between instances of dependent types

When attempting to formalize the class which corresponds to an algebraic structure (for example the class of all monoids), a natural design is to create a type monoid (a:Type) as a product type which models all the required fields (an element e:a, an operator app : a -> a -> a, proofs that the monoid laws are satisfied etc.). In doing so, we are creating a map monoid: Type -> Type. A possible drawback of this approach is that given a monoid m:monoid a (a monoid with support type a) and m':monoid b (a monoid wih support type b), we cannot even write the equality m = m' (let alone prove it) because it is ill-typed. An alternative design would be to create a type monoid where the support type is just another field a:Type, so that given m m':monoid, it is always meaningful to ask whether m = m'. Somehow, one would like to argue that if m and m' have the same supports (a m = a m) and the operators are equals (app m = app m', which may be achieved thanks to some extensional equality axiom), and that the proof fields do not matter (because we have some proof irrelevance axiom) etc. , then m = m'. Unfortunately, we can't event express the equality app m = app m' because it is ill-typed...
To simplify the problem, suppose we have:
Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
.
I would like to have results of the form:
forall (a b:Type) (x:a) (y:b), a = b -> x = y -> make a x = make b y.
This statement is ill-typed so we can't have it.
I may have axioms allowing me to prove that two types a and b are same, and I may be able to show that x and y are indeed the same too, but I want to have a tool allowing me to conclude that make a x = make b y. Any suggestion is welcome.
A low-tech way to prove this is to insert a manual type-cast, using the provided equality. That is, instead of having an assumption x = y, you have an assumption (CAST q x) = y. Below I explicitly write the cast as a match, but you could also make it look nicer by defining a function to do it.
Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
Lemma ex : forall (a b:Type) (x:a) (y:b) (q: a = b), (match q in _ = T return T with eq_refl => x end) = y -> make a x = make b y.
Proof.
destruct q.
intros q.
congruence.
Qed.
There is a nicer way to hide most of this machinery by using "heterogenous equality", also known as JMeq. I recommend the Equality chapter of CPDT for a detailed introduction. Your example becomes
Require Import Coq.Logic.JMeq.
Infix "==" := JMeq (at level 70, no associativity).
Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
Lemma ex : forall (a b:Type) (x:a) (y:b), a = b -> x == y -> make a x = make b y.
Proof.
intros.
rewrite H0.
reflexivity.
Qed.
In general, although this particular theorem can be proved without axioms, if you do the formalization in this style you are likely to encounter goals that can not be proven in Coq without axioms about equality. In particular, injectivity for this kind of dependent records is not provable. The JMEq library will automatically use an axiom JMeq_eq about heterogeneous equality, which makes it quite convenient.

What is difference between `destruct` and `case_eq` tactics in Coq?

I understood destruct as it breaks an inductive definition into its constructors. I recently saw case_eq and I couldn't understand what it does differently?
1 subgoals
n : nat
k : nat
m : M.t nat
H : match M.find (elt:=nat) n m with
| Some _ => true
| None => false
end = true
______________________________________(1/1)
cc n (M.add k k m) = true
In the above context, if I do destruct M.find n m it breaks H into true and false whereas case_eq (M.find n m) leaves H intact and adds separate proposition M.find (elt:=nat) n m = Some v, which I can rewrite to get same effect as destruct.
Can someone please explain me the difference between the two tactics and when which one should be used?
The first basic tactic in the family of destruct and case_eq is called case. This tactic modifies only the conclusion. When you type case A and A has a type T which is inductive, the system replaces A in the goal's conclusion by instances of all the constructors of type T, adding universal quantifications for the arguments of these constructors, if needed. This creates as many goals as there are constructors in type T. The formula A disappears from the goal and if there is any information about A in an hypothesis, the link between this information and all the new constructors that replace it in the conclusion gets lost. In spite of this, case is an important primitive tactic.
Loosing the link between information in the hypotheses and instances of A in the conclusion is a big problem in practice, so developers came up with two solutions: case_eq and destruct.
Personnally, when writing the Coq'Art book, I proposed that we write a simple tactic on top of case that keeps a link between A and the various constructor instances in the form of an equality. This is the tactic now called case_eq. It does the same thing as case but adds an extra implication in the goal, where the premise of the implication is an equality of the form A = ... and where ... is an instance of each constructor.
At about the same time, the tactic destruct was proposed. Instead of limiting the effect of replacement in the goal's conclusion, destruct replaces all instances of A appearing in the hypotheses with instances of constructors of type T. In a sense, this is cleaner because it avoids relying on the extra concept of equality, but it is still incomplete because the expression A may be a compound expression f B, and if B appears in the hypothesis but not f B the link between A and B will still be lost.
Illustration
Definition my_pred (n : nat) := match n with 0 => 0 | S p => p end.
Lemma example n : n <= 1 -> my_pred n <= 0.
Proof.
case_eq (my_pred n).
Gives the two goals
------------------
n <= 1 -> my_pred n = 0 -> 0 <= 0
and
------------------
forall p, my_pred n = S p -> n <= 1 -> S p <= 0
the extra equality is very useful here.
In this question I suggested that the developer use case_eq (a == b) when (a == b) has type bool because this type is inductive and not very informative (constructors have no argument). But when (a == b) has type {a = b}+{a <> b} (which is the case for the string_dec function) the constructors have arguments that are proofs of interesting properties and the extra universal quantification for the arguments of the constructors are enough to give the relevant information, in this case a = b in a first goal and a <> b in a second goal.

Defining isomorphism classes in Coq

How to define isomorphism classes in Coq?
Suppose I have a record ToyRec:
Record ToyRec {Labels : Set} := {
X:Set;
r:X->Labels
}.
And a definition of isomorphisms between two objects of type ToyRec, stating that two
objects T1 and T2 are isomorphic if there exists a bijection f:T1.(X)->T2.(X) which preserves the label of mapped elements.
Definition Isomorphic{Labels:Set} (T1 T2 : #ToyRec Labels) : Prop :=
exists f:T1.(X)->T2.(X), (forall x1 x2:T1.(X), f x1 <> f x2) /\
(forall x2:T2.(X), exists x1:T1.(X), f x1 = f x2) /\
(forall x1:T1.(X) T1.(r) x1 = T2.(r) (f x1)).
Now I would like to define a function that takes an object T1 and returns a set
containing all objects that are isomorphic to T1.
g(T1) = {T2 | Isomorphic T1 T2}
How one does such a thing in coq? I know that I might be reasoning too set theoretically
here, but what would be the right type theoretic notion of isomorphism class? Or even more basically, how one would define a set (or type) of all elemenets satisfying a given property?
It really depends on what you want to do with it. In Coq, there is a comprehension type {x : T | P x} which is the type of all elements x in type T that satisfy property P. However, it is a type, meaning that it is used to classify other terms, and not a data-structure you can compute with in the traditional sense. Thus, you can use it, for instance, to write a function on T that only works on elements that satisfy P (in which case the type of the function would be {x : T | P x} -> Y, where Y is its result type), but you can't use it to, say, write a function that computes how many elements of T satisfy P.
If you want to compute with this set, things become a bit more complicated. Let's suppose P is a decidable property so that things become a bit easier. If T is a finite type, then you can a set data-structure that has a comprehension operator (have a look at the Ssreflect library, for instance). However, this breaks when T is infinite, which is the case of your ToyRec type. As Vinz said, there's no generic way of constructively building this set as a data-structure.
Perhaps it would be easier to have a complete answer if you explained what you want to do with this type exactly.