How to express subset relation in Coq? - coq

How can I describe in Coq that one set Y is a subset of another set X?
I tested the following:
Definition subset (Y X:Set) : Prop :=
forall y:Y, y:X.
, trying to express that if an element y is in Y, then y is in X. But this generates type errors about y, not surprisingly.
Is there an easy way to define subset in Coq?

Here is how it is done in the standard library (Coq.Logic.ClassicalChoice):
Definition subset (U:Type) (P Q:U->Prop) : Prop := forall x, P x -> Q x.
Unary predicates P and Q represent some subsets of the (universal) set U, so the above definition reads: whenever some x is in P, it is in Q at the same time.
A somewhat similar defintion can be found in Coq.MSets.MSetInterface:
Definition Subset s s' := forall a : elt, In a s -> In a s'.
where In has type elt -> t -> Prop, which means that some element of type elt is a member of a set of type t.

Related

Why does Coq object to the following PairUsualDecidableTypeFull module type?

In Coq.Structures.EqualitiesFacts, there is a convenient PairUsualDecidableType module type for building a UsualDecidableType module from the cartesian product of two others.
It seems that there is no corresponding PairUsualDecidableTypeFull module type for doing the same with UsualDecidableTypeFulls.
I tried to create one, beginning as follows:
Module PairUsualDecidableTypeFull(D1 D2:UsualDecidableTypeFull) <: UsualDecidableTypeFull.
Definition t := (D1.t * D2.t)%type.
Definition eq := #eq t.
Instance eq_equiv : Equivalence eq := _.
Definition eq_refl : forall x : t, x = x. Admitted.
Definition eq_sym : forall x y : t, x = y -> y = x. Admitted.
Definition eq_trans : forall x y z : t, x = y -> y = z -> x = z. Admitted.
Definition eq_dec : forall x y, { eq x y }+{ ~eq x y }. Admitted.
Definition eqb : t -> t -> bool. Admitted.
Definition eqb_eq : forall x y : t, eqb x y = true <-> x = y. Admitted.
End PairUsualDecidableTypeFull.
but Coq complains that:
Signature components for label eq_refl do not match: the body of definitions differs.
I do not understand what "signature components" means. Given that the output of Print UsualDecidableTypeFull includes:
Definition eq_refl : forall x : t, #Logic.eq t x x.
the type of eq_refl at least looks right. What else could be wrong?
I am a total amateur and extremely new to Coq, running version 8.9.0. Perhaps what I'm trying to do doesn't make sense for some reason; the fact that the standard libraries include PairUsualDecidableType but not PairUsualDecidableTypeFull makes me a little suspicious I've missed something.
Any guidance would be most welcome, and thanks in advance.
First, the standard library is known to be incomplete. Thus, the fact that one particular definition/lemma/module is not provided does not mean that it should not be there. And it is even more true for modules, since the module system of Coq is little used.
Concerning your problem, in Coq, the boundary between Module and Module Type is thin. In particular, you can have definitions in Module Type, and not only declarations (I am not sure that these terms "definition" and "declaration" are the right words to use here, but I hope it is at least understandable). For instance,
Module Type Sig.
Parameter n : nat.
Definition plus x y := x + y.
End Sig.
is a signature declaring a field n of type nat and defining a field plus as the addition of natural numbers. When writing a module that must comply with this signature, you can implement the declarations as you wish, as long as types correspond, but for definitions, you must basically write exactly the same body as in the signature. For instance, you can write:
Module M <: Sig.
Definition n := 3.
Definition plus x y := x + y.
End M.
You can observe which fields are declarations and which are definitions using Print: declarations appear as Parameter and definitions appear as Definition (but the actual body of the definition is not printed, which is admittedly confusing). In your case, eq, eq_equiv, eq_refl, eq_sym and eq_trans are all definitions in UsualDecidableTypeFull, so you have no choice for their implementation, you must define eq as Logic.eq, eq_equiv as eq_equivalence (cf. the definitions in Equalities), etc. When using Admitted to implement eq_refl, you are using a body different from the one given in the signature. Your module definition is thus rejected with the message the body of definitions differs.
If I come back to your initial problem of writing a functor PairUsualDecidableTypeFull, by digging into Equalities and EqualitiesFacts, I wrote this implementation that reuses as much as possible existing components of the standard library.
Module DT_to_Full (D:DecidableType') <: DecidableTypeFull.
Include Backport_DT (D).
Include HasEqDec2Bool.
End DT_to_Full.
Module PairUsualDecidableTypeFull (D1 D2:UsualDecidableTypeFull)
<: UsualDecidableTypeFull.
Module M := PairUsualDecidableType D1 D2.
Include DT_to_Full (M).
End PairUsualDecidableTypeFull.
I managed to work around this by simply "wrapping" Coq's UsualDecidableTypeFull by defining:
Module Type UDTFW <: UsualDecidableType.
Parameter t : Type.
Definition eq := #Logic.eq t.
Definition eq_equiv : Equivalence eq := _.
Parameter eq_refl : forall x : t, x = x.
Parameter eq_sym : forall x y : t, x = y -> y = x.
Parameter eq_trans : forall x y z : t, x = y -> y = z -> x = z.
Parameter eq_dec : forall x y, { #Logic.eq t x y }+{ ~#Logic.eq t x y }.
Parameter eqb : t -> t -> bool.
Parameter eqb_eq : forall x y : t, eqb x y = true <-> x = y.
End UDTFW.
together with:
Module Make_UDTFW (X : UsualDecidableTypeFull) <: UDTFW.
Definition t := X.t.
Definition eq := X.eq.
Definition eq_equiv := X.eq_equiv.
Definition eq_refl := X.eq_refl.
Definition eq_sym := X.eq_sym.
Definition eq_trans := X.eq_trans.
Definition eq_dec := X.eq_dec.
Definition eqb := X.eqb.
Definition eqb_eq := X.eqb_eq.
End Make_UDTFW.
Having introduced this bizarre-looking extra level of indirection at the module level, the defintion of PairUsualDecidableTypeFull in the question actually works, except using UDTFW everywhere intead of UsualDecidableTypeFull.
This rather ugly workaround turns out to suffice for my purposes but I'd be very interested to understand what the real issue is here.

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.

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.

Messing around with category theory

Motivation: I am attempting to study category theory while creating a Coq formalization of the ideas I find in whatever textbook I follow. In order to make this formalization as simple as possible, I figured I should identify objects with their identity arrow, so a category can be reduced to a set (class, type) of arrows X with a source mapping s:X->X, target mapping t:X->X, and composition mapping product : X -> X -> option X which is a partial mapping defined for t f = s g. Obviously the structure (X,s,t,product) should follow various properties. For the sake of clarity, I am spelling out the formalization I chose below, but there is no need to follow it I think in order to read my question:
Record Category {A:Type} : Type := category
{ source : A -> A
; target : A -> A
; product: A -> A -> option A
; proof_of_ss : forall f:A, source (source f) = source f
; proof_of_ts : forall f:A, target (source f) = source f
; proof_of_tt : forall f:A, target (target f) = target f
; proof_of_st : forall f:A, source (target f) = target f
; proof_of_dom: forall f g:A, target f = source g <-> product f g <> None
; proof_of_src: forall f g h:A, product f g = Some h -> source h = source f
; proof_of_tgt: forall f g h:A, product f g = Some h -> target h = target g
; proof_of_idl: forall a f:A,
a = source a ->
a = target a ->
a = source f ->
product a f = Some f
; proof_of_idr: forall a f:A,
a = source a ->
a = target a ->
a = target f ->
product f a = Some f
; proof_of_asc:
forall f g h fg gh:A,
product f g = Some fg ->
product g h = Some gh ->
product fg h = product f gh
}
.
I have no idea how practical this is and how far it will take me. I see this as an opportunity to learn category theory and Coq at the same time.
Problem: My first objective was to create a 'Category' which would resemble as much as possible the category Set. In a set theoretic framework, I would probably consider the class of triplets (a,b,f) where f is a map with domain a and range a subset of b. With this in mind I tried:
Record Arrow : Type := arrow
{ dom : Type
; cod : Type
; arr : dom -> cod
}
.
So that Arrow becomes my base type on which I could attempt building a structure of category. I start embedding Type into Arrow:
Definition id (a : Type) : Arrow := arrow a a (fun x => x).
which allows me to define the source and target mappings:
Definition domain (f:Arrow) : Arrow := id (dom f).
Definition codomain (f:Arrow) : Arrow := id (cod f).
Then I move on to defining a composition on Arrow:
Definition compose (f g: Arrow) : option Arrow :=
match f with
| arrow a b f' =>
match g with
| arrow b' c g' =>
match b with
| b' => Some (arrow a c (fun x => (g' (f' x))))
| _ => None
end
end
end.
However, this code is illegal as I get the error:
The term "f' x" has type "b" while it is expected to have type "b'".
Question: I have the feeling I am not going to get away with this, My using Type naively would take me to some sort of Russel paradox which Coq will not allow me to do. However, just in case, is there a way to define compose on Arrow?
Your encoding does not work in plain Coq because of the constructive nature of the theory: it is not possible to compare two sets for equality. If you absolutely want to follow this approach, Daniel's comment sketches a solution: you need to assume a strong classical principle to be able to check whether the endpoints of two arrows match, and then manipulate an equality proof to make Coq accept the definition.
Another approach is to have separate types for arrows and objects, and use type dependency to express the compatibility requirement on arrow endpoints. This definition requires only three axioms, and considerably simplifies the construction of categories:
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Record category : Type := Category {
obj : Type;
hom : obj -> obj -> Type;
id : forall {X}, hom X X;
comp : forall X Y Z, hom X Y -> hom Y Z -> hom X Z;
(* Axioms *)
idL : forall X Y (f : hom X Y), comp id f = f;
idR : forall X Y (f : hom X Y), comp f id = f;
assoc : forall X Y Z W
(f : hom X Y) (g : hom Y Z) (h : hom Z W),
comp f (comp g h) = comp (comp f g) h
}.
We can now define the category of sets and ask Coq to automatically prove the axioms for us.
Require Import Coq.Program.Tactics.
Program Definition Sets : category := {|
obj := Type;
hom X Y := X -> Y;
id X := fun x => x;
comp X Y Z f g := fun x => g (f x)
|}.
(This does not lead to any circularity paradoxes, because of Coq's universe mechanism: Coq understands that the Type used in this definition is actually smaller than the one used to define category.)
This encoding is sometimes inconvenient due to the lack of extensionality in Coq's theory, because it prevents certain axioms from holding. Consider the category of groups, for example, where the morphisms are functions that commute with the group operations. A reasonable definition for these morphisms could be as follows (assuming that there is some type group representing groups, with * denotes multiplication and 1 denotes the neutral element).
Record group_morphism (X Y : group) : Type := {
mor : X -> Y;
mor_1 : mor 1 = 1;
mor_m : forall x1 x2, mor (x1 * x2) = mor x1 * mor x2
}.
The problem is that the properties mor_1 and mor_m interfere with the notion of equality for elements of group_morphism, making the proofs for associativity and identity that worked for Sets break. There are two solutions:
Adopt extra axioms into the theory so that the required properties still go through. In the above example, you would need proof irrelevance:
proof_irrelevance : forall (P : Prop) (p q : P), p = q.
Change the category axioms so that the identities are valid up to some equivalence relation specific to that category, instead of the plain Coq equality. This approach is followed here, for example.

Coq - use Prop (True | False) in if ... then ... else

I'm kind of new to Coq.
I'm trying to implement a generic version of insertion sort. I'm implementing is as a module that takes a Comparator as a parameter. This Comparator implements comparison operators (such as is_eq, is_le, is_neq, etc.).
In insertion sort, in order to insert, I must compare two elements in the input list, and based on the result of the comparison, insert the element into the correct location.
My problem is that the implementations of the comparison operators are type -> type -> prop (i need them to be like this for implementation of other types/proofs). I'd rather not create type -> type -> bool versions of the operators if it can be avoided.
Is there any way to convert a True | False prop to a bool for use in a if ... then ... else clause?
The comparator module type:
Module Type ComparatorSig.
Parameter X: Set.
Parameter is_eq : X -> X -> Prop.
Parameter is_le : X -> X -> Prop.
Parameter is_neq : X -> X -> Prop.
Infix "=" := is_eq (at level 70).
Infix "<>" := (~ is_eq) (at level 70).
Infix "<=" := is_le (at level 70).
Parameter eqDec : forall x y : X, { x = y } + { x <> y }.
Axiom is_le_trans : forall (x y z:X), is_le x y -> is_le y z -> is_le x z.
End ComparatorSig.
An implementation for natural numbers:
Module IntComparator <: Comparator.ComparatorSig.
Definition X := nat.
Definition is_le x y := x <= y.
Definition is_eq x y := eq_nat x y.
Definition is_neq x y:= ~ is_eq x y.
Definition eqDec := eq_nat_dec.
Definition is_le_trans := le_trans.
End IntComparator.
The insertion part of insertion sort:
Fixpoint insert (x : IntComparator .X) (l : list IntComparator .X) :=
match l with
| nil => x :: nil
| h :: tl => if IntComparator.is_le x h then x :: h :: tl else h :: (insert x tl)
end.
(obviously, the insert fixpoint doesn't work, since is_le is returns Prop and not bool).
Any help is appreciated.
You seem to be a bit confused about Prop.
is_le x y is of type Prop, and is the statement x is less or equal to y. It is not a proof that this statement is correct. A proof that this statement is correct would be p : is_le x y, an inhabitant of that type (i.e. a witness of that statement's truth).
This is why it does not make much sense to pattern match on IntComparator.is_le x h.
A better interface would be the following:
Module Type ComparatorSig.
Parameter X: Set.
Parameter is_le : X -> X -> Prop.
Parameter is_le_dec : forall x y, { is_le x y } + { ~ is_le x y }.
In particular, the type of is_le_dec is that of a decision procedure for the property is_le, that is, it returns either a proof that x <= y, or a proof that ~ (x <= y). Since this is a type with two constructors, you can leverage the if sugar:
... (if IntComparator.is_le_dec x h then ... else ...) ...
This is, in some sense, an enhanced bool, which returns a witness for what it is trying to decide. The type in question is called sumbool and you can learn about it here:
http://coq.inria.fr/library/Coq.Init.Specif.html#sumbool
In general, it does not make sense to talk about True or False in executing code.
First, because these live in Prop, which means that they cannot be computationally relevant as they will be erased.
Second, because they are not the only inhabitants of Prop. While true and false are the only values of type bool, which implies you can pattern-match, the type Prop contains an infinite number of elements (all the statements you can imagine), thus it makes no sense to try and pattern-match on a element of type Prop.