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.
Related
Let's define two helper types:
Inductive AB : Set := A | B.
Inductive XY : Set := X | Y.
Then two other types that depend on XY and AB
Inductive Wrapped : AB -> XY -> Set :=
| W : forall (ab : AB) (xy : XY), Wrapped ab xy
| WW : forall (ab : AB), Wrapped ab (match ab with A => X | B => Y end)
.
Inductive Wrapper : XY -> Set :=
WrapW : forall (xy : XY), Wrapped A xy -> Wrapper xy.
Note the WW constructor – it can only be value of types Wrapped A X and Wrapped B Y.
Now I would like to pattern match on Wrapper Y:
Definition test (wr : Wrapper Y): nat :=
match wr with
| WrapW Y w =>
match w with
| W A Y => 27
end
end.
but I get error
Error: Non exhaustive pattern-matching: no clause found for pattern WW _
Why does it happen? Wrapper forces contained Wrapped to be A version, the type signature forces Y and WW constructor forbids being A and Y simultaneously. I don't understand why this case is being even considered, while I am forced to check it which seems to be impossible.
How to workaround this situation?
Let's simplify:
Inductive MyTy : Set -> Type :=
MkMyTy : forall (A : Set), A -> MyTy A.
Definition extract (m : MyTy nat) : nat :=
match m with MkMyTy _ x => S x end.
This fails:
The term "x" has type "S" while it is expected to have type "nat".
wat.
This is because I said
Inductive MyTy : Set -> Type
This made the first argument to MyTy an index of MyTy, as opposed to a parameter. An inductive type with a parameter may look like this:
Inductive list (A : Type) : Type :=
| nil : list A
| cons : A -> list A -> list A.
Parameters are named on the left of the :, and are not forall-d in the definition of each constructor. (They are still present in the constructors' types outside of the definition: cons : forall (A : Type), A -> list A -> list A.) If I make the Set a parameter of MyTy, then extract can be defined:
Inductive MyTy (A : Set) : Type :=
MkMyTy : A -> MyTy A.
Definition extract (m : MyTy nat) : nat :=
match m with MkMyTy _ x => S x end.
The reason for this is that, on the inside, a match ignores anything you know about the indices of the scrutinee from the outside. (Or, rather, the underlying match expression in Gallina ignores the indices. When you write a match in the source code, Coq tries to convert it into the primitive form while incorporating information from the indices, but it often fails.) The fact that m : MyTy nat in the first version of extract simply did not matter. Instead, the match gave me S : Set (the name was automatically chosen by Coq) and x : S, as per the constructor MkMyTy, with no mention of nat. Meanwhile, because MyTy has a parameter in the second version, I actually get x : nat. The _ is really a placeholder this time; it is mandatory to write it as _, because there's nothing to match, and you can Set Asymmetric Patterns to make it disappear.
The reason we distinguish between parameters and indices is because parameters have a lot of restrictions—most notably, if I is an inductive type with parameters, then the parameters must appear as variables in the return type of each constructor:
Inductive F (A : Set) : Set := MkF : list A -> F (list A).
(* ^--------^ BAD: must appear as F A *)
In your problem, we should make parameters where we can. E.g. the match wr with Wrap Y w => _ end bit is wrong, because the XY argument to Wrapper is an index, so the fact that wr : Wrapper Y is ignored; you would need to handle the Wrap X w case too. Coq hasn't gotten around to telling you that.
Inductive Wrapped (ab : AB) : XY -> Set :=
| W : forall (xy : XY), Wrapped ab xy
| WW : Wrapped ab (match ab with A => X | B => Y end).
Inductive Wrapper (xy : XY) : Set := WrapW : Wrapped A xy -> Wrapper xy.
And now your test compiles (almost):
Definition test (wr : Wrapper Y): nat :=
match wr with
| WrapW _ w => (* mandatory _ *)
match w with
| W _ Y => 27 (* mandatory _ *)
end
end.
because having the parameters gives Coq enough information for its match-elaboration to use information from Wrapped's index. If you issue Print test., you can see that there's a bit of hoop-jumping to pass information about the index Y through the primitive matchs which would otherwise ignore it. See the reference manual for more information.
The solution turned out to be simple but tricky:
Definition test (wr : Wrapper Y): nat.
refine (match wr with
| WrapW Y w =>
match w in Wrapped ab xy return ab = A -> xy = Y -> nat with
| W A Y => fun _ _ => 27
| _ => fun _ _ => _
end eq_refl eq_refl
end);
[ | |destruct a]; congruence.
Defined.
The issue was that Coq didn't infer some necessary invariants to realize that WW case is ridiculous. I had to explicitly give it a proof for it.
In this solution I changed match to return a function that takes two proofs and brings them to the context of our actual result:
ab is apparently A
xy is apparently Y
I have covered real cases ignoring these assumptions, and I deferred "bad" cases to be proven false later which turned to be trivial. I was forced to pass the eq_refls manually, but it worked and does not look that bad.
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.
It is a standard example of beginner's textbooks on category theory to argue that a preorder gives rise to a category (where the hom-set hom(x,y) is a singleton or empty depending on whether x <= y). When attempting to formalize this idea in coq, it is natural to view an arrow of as a triple (x,y,pxy) where x y:A (A being a type on which we have a preorder) and pxy is a proof that x <= y. So naturally, when attempting to define a composition of two arrows (x,y,pxy) and (y',z,pyz), we need to returnSome arrow whenever y = y' (or None otherwise). This implies that we are able to test for equality within the function, and compute a proof (the last field of our triple, which may rely on the fact that things are equal).
For the sake of this question, suppose I have:
Parameter eq_dec : forall {A:Type}, A -> A -> bool.
and:
Axiom eq_dec_correct : forall (A:Type) (x y:A),
eq_dec x y = true -> x = y. (* don't care about equivalence here *)
and let us assume I am attempting something simpler than defining composition between arrows, by writing a function which returns a proof that x = y whenever x = y.
Definition test {A:Type} (x y : A) : option (x = y) :=
match eq_dec x y with
| true => Some (eq_dec_correct A x y _)
| false => None
end.
This doesn't work of course, but probably gives you the idea of what I am trying to achieve. Any suggestion is greatly appreciated.
EDIT: Ok it seems this is a case of 'convoy pattern'. I have found this link which suggested to me:
Definition test (A:Type) (x y:A) : option (x = y) :=
match eq_dec x y as b return eq_dec x y = b -> option (x = y) with
| true => fun p => Some (eq_dec_correct A x y p)
| false => fun _ => None
end (eq_refl (eq_dec x y)).
This seems to be working. It is a bit magical and confusing but I'll get my head round it.
Inductive ty: Set :=
| I
| O.
Definition f (x: ty) (y: ty): nat :=
if x = y then 0 else 1.
I want the function f to compare two terms of type ty but it does not compile and I see this error:
The term x = y has type Prop which is not a (co-)inductive type.
You need to prove that equality is decidable for ty (which can be done automatically using decide equality) and then use that definition in the if ... then ... else ... statement. Concretely:
Inductive ty: Set :=
| I
| O.
Definition ty_eq_dec : forall (x y : ty), { x = y } + { x <> y }.
Proof.
decide equality.
Defined.
Definition f (x: ty) (y: ty): nat :=
if ty_eq_dec x y then 0 else 1.
You can use match to compare the elements of inductive data types.
Definition f x y := match x,y with I, I | O, O => 0 | _,_ => 1 end.
decide equality is a more general tactic and works for infinite sets, but it is good to know that it is match that is doing the real work.
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.