Equality in COQ for enumerated types - coq

I have a finite enumerated type (say T) in COQ and want to check elements for equality. This means, I need a function
bool beq_T(x:T,y:T)
The only way I managed to define such a function, is with a case by case analysis. This results in lots of match statements and looks very cumbersome. Therefore, I wonder if there is not a simpler way to achieve this.

Even simpler: Scheme Equality for ... generates two functions returning respectively a boolean and a sumbool.

The bad news is that the program that implements beq_T must necessarily consist of a large match statement on both of its arguments. The good news is that you can automatically generate/synthesize this program using Coq's tactic language. For example, given the type:
Inductive T := t0 | t1 | t2 | t3.
You can define beq_T as follows. The first two destruct tactics synthesize the code necessary to match on both x and y. The match tactic inspects the branch of the match that it is in, and depending on whether x = y, the tactic either synthesises the program that returns true or false.
Definition beq_T (x y:T) : bool.
destruct x eqn:?;
destruct y eqn:?;
match goal with
| _:x = ?T, _:y = ?T |- _ => exact true
| _ => exact false
end.
Defined.
If you want to see the synthesized program, run:
Print beq_T.
Thankfully, Coq already comes with a tactic that does almost what you want. It is called decide equality. It automatically synthesizes a program that decides whether two elements of a type T are equal. But instead of just returning a boolean value, the synthesized program returns a proof of the (in)equality of the two elements.
Definition eqDec_T (x y:T) : {x = y} + {x <> y}.
decide equality.
Defined.
With that program synthesized, it is easy to implement beq_T.
Definition beq_T' {x y:T} : bool := if eqDec_T x y then true else false.

Related

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).

How to define a specific field in Coq

I am trying to construct GF(2) in Coq using the standard library definition of a field over the standard library's boolean implementation.
to be clear:
"true" should be the field's "1" element.
"false" should be the field's "0" element.
"xorb" should be addititon.
"andb" should be multiplication.
I'd expect that I should have to pass this information to some record from here and provide a correctness proof. However, I can't figure out how to set this up.
In the standard library field structure, you first need to exhibit the ring structure on which this field will rest. For this ring structure we need to figure out what serves as the opposite function and what serves as the subtraction function. The answer is: the opposite is the identity function and the subtraction is also xorb. So we first want to express that false, true, xorb, andb, xorb, and (fun x => x) constitute a ring. In the case, of Coq, we also need to specify what equivalence relation we will use to identify two terms of the ring, in this case we pick the plain equality #eq bool. To describe such a ring structure, we need to create an object of type.
Ring_theory.ring_theory false true xorb andb xorb (fun x => x) (#eq bool).
The simplest way to do that, is to just say that we want to do it, without providing the value for the structure, and use proof mode to help discover all the propositions that need to be verified.
Definition GF2_ring :
Ring_theory.ring_theory false true xorb andb xorb (fun x => x) (#eq bool).
The answer of the system just repeats the expected type. We can now tell Coq that we want to apply the record constructor.
apply Ring_theory.mk_rt.
This creates 9 goals, each of which verifies one of the expected properties of a ring: neutral element properties, associativity, commutativity, distributivity, and property of the opposite function.
You can search for existing theorems expressing all these properties, but another possibility is to verify these properties by checking all possible cases for all variables. This is done in the following complete proof.
Require Import Field.
Definition GF2_ring :
Ring_theory.ring_theory false true xorb andb xorb (fun x => x) (#eq bool).
Proof.
apply Ring_theory.mk_rt;
solve[now intros [] | now intros [] [] | now intros [] [] []].
Qed.
A similar proof structure can be used to complete the field structure.
Definition GF2_Field :
field_theory false true xorb andb xorb (fun x => x) andb (fun x => x) (#eq bool).
constructor; try solve[exact GF2_ring | now easy ].
now intros [] abs; auto; try case abs.
Qed.
Now, what does give to you? The ring_theory and field_theory actually intermediate tools for the implimentation of the ring and field tactics. So you can use the object GF2_Field in the Add Field command, but in the case of GF(2), these tactics are not as useful as in the case of number fields.
If you are interested in algebraic structures, I think you should rather look at developments like mathematical components or math classes.

how to figure out what "=" means in different types in 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.

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.

Decoupling the data to be manipulated from the proofs that the manipulations are justified

I have a type of lists whose heads and tails must be in a certain sense "compatible":
Inductive tag := A | B. (* Just an example *)
Inductive element : tag -> tag -> Set :=
| AA : element A A
| AB : element A B
| BB : element B B. (* Also just an example *)
Inductive estack : tag -> tag -> Set :=
| ENil : forall t, estack t t
| ECons : forall r s t, element r s -> estack s t -> estack r t.
However, I do not like this code very much, for the following reasons:
It is not modular: The ad-hoc list data constructors are intrinsically coupled with the proofs that the heads and tails are compatible - the tags.
It does not favor code reuse: I am forced to redefine the usual list functions (such as list concatenation) and re-prove the usual list theorems (such as the associativity of list concatenation).
I have a different approach in mind, which consists of three steps:
Defining a single type of tagged elements (as opposed to a family of tagged types of elements):
Inductive taggedElement := Tagged : forall t1 t2, element t1 t2 -> taggedElement.
Defining the type of arbitrary (that is, either valid or invalid) lists of tagged elements:
Definition taggedElementStack := list taggedElement.
Defining a valid list of tagged elements as a tuple whose elements are an arbitrary list of tagged elements and a proof that the elements are compatible with the adjacent ones.
(* I have no idea how to do this in Coq, hence the question!
*
* I am going to use pseudomathematical notation. I am not well versed in either
* mathematics or theoretical computer science, so please do not beat me with a
* stick if I say something that is completely bogus!
*
* I want to construct the type
*
* (tes : taggedElementStack, b : proof that P(tes) holds)
*
* where P(tes) is a predicate that is only true when, for every sublist of tes,
* including tes itself, the heads and tails are compatible.
*)
How would I perform the third step in Coq?
Look at your estack, what does it do? Generalize! element is just a relation (A -> A -> Set), tag is just a Set. What do you get?
Inductive RTList {I : Set} (X : Rel I) : Rel I :=
| RTNil : forall {i : I}, RTList X i i
| RTCons : forall {i j k : I}, X i j -> RTList X j k -> RTList X i k.
(Rel ist just a Definition with Rel I = I -> I -> Set.)
Reflexive-transitive closure! That is common, reusable and modular. Or so you'd think.
The only implementation I found in Coq's libs is in Coq.Relations.Relation_Operators, named clos_refl_trans, differently structured and locked into Prop (all according to the docs, didn't try it).
You'll probably have to re-implement that or find a library somewhere. At least, you'll only have to do this once (or up to three times for Set, Prop and Type).
Your other idea will probably be harder to manage. Look at NoDup for something that's similar to your description, you might be able to reuse the pattern. If you really want that. NoDup uses In, which is a function that checks if an element is in a list. The last time I tried using it, I found it considerably harder to solve proofs involving In. You can't just destruct but have to apply helper lemmas, you have to carefully unfold exactly $n levels, folding back is hard etc. etc. I'd suggest that unless it's truly necessary, you'd better stick with data types for Props.