I am working with a definition in coq which need to yield something from a Theorem, but cannot destruct in the definition.
Theorem sp : forall (X : Type) (T : X -> Prop)..... , exists (a : X), T a.
Definition yield_sp : (X : Type) (T : X -> Prop) (H : sp X T .....)..... : X.
When I try to destruct H, coq warns that
Case analysis on sort Type is not allowed for inductive definition ex.
I would like to know the reason for it, and further, how to use definition to yield an element from an "exists" proposition.
You cannot extract the witness out of an existence proof. There are a few options:
Change the statement of the proof to {x : T | P x}, which behaves more-or-less like the existential quantifier, but supports a projection function proj1_sig : {x : T | P x} -> T.
Assume a choice axiom, as in https://coq.inria.fr/library/Coq.Logic.ClassicalChoice.html
If you are quantifying over a countable type and your proposition is decidable, you can use the trick in this question to extract the witness.
Related
I am learning the Coq language and trying to prove the following statement:
Lemma ex4: forall (X : Set) (P : X -> Prop), ~(forall x, ~ (P x)) -> (exists x, (P x)).
In the beginning of my proof:
Proof.
intros X P A.
I arrive at the point where I have the assumptions
X : Set
P : X -> Prop
A : ~ (forall x : X, ~ P x)
I now want to apply de morgan law on A to get an assumption
B : exists x : X, ~ (~ P x) (*** Or something similar ***)
but I can't find a way to correctly use the library function. The following line
apply (not_all_ex_not P).
throws an error:
In environment
X : Set
P : X -> Prop
A : ~ (forall x : X, ~ P x)
The term "P" has type "X -> Prop" while it is expected to have type "Type".
I import the not_all_ex_not from using the command Require Import Coq.Logic.Classical.
What am I doing wrong?
Use apply not_all_ex_not in A instead (or apply (not_all_ex_not X (fun x => ~ P x)) in A).
Explanation In Coq, you need to explicitly apply type arguments to polymorphic functions and lemmas, unless they are marked as implicit. The not_all_x_not lemma has only explicit arguments, and the first argument is the argument type of the predicate, which is why your attempt did not work. The in A is needed because your goal does not syntactically match the conclusion of not_all_ex_not.
data _∈_ {X : Set} (x : X) : (xs : List X) → Set where
here! : {xs : List X} → x ∈ x ∷ xs
there : {xs : List X} {y : X} (pr : x ∈ xs) → x ∈ y ∷ xs
remove : {X : Set} {x : X} (xs : List X) (pr : x ∈ xs) → List X
remove (_ ∷ xs) here! = xs
remove (y ∷ xs) (there pr) = y ∷ remove xs pr
I am trying to translate the above definition from Agda to Coq and am running into difficulties.
Inductive Any {A : Type} (P : A -> Type) : list A -> Prop :=
| here : forall {x : A} {xs : list A}, P x -> Any P (x :: xs)
| there : forall {x : A} {xs : list A}, Any P xs -> Any P (x :: xs).
Definition In' {A : Type} (x : A) xs := Any (fun x' => x = x') xs.
Fixpoint remove {A : Type} {x : A} {l : list A} (pr : In' x l) : list A :=
match l, pr with
| [], _ => []
| _ :: ls, here _ _ => ls
| x :: ls, there _ pr => x :: remove pr
end.
Incorrect elimination of "pr0" in the inductive type "#Any":
the return type has sort "Type" while it should be "Prop".
Elimination of an inductive object of sort Prop
is not allowed on a predicate in sort Type
because proofs can be eliminated only to build proofs.
In addition to this error, if I leave the [] case out Coq is asks me to provide it despite it being absurd.
Up to this point, I've thought that Agda and Coq were the same languages with a different front end, but now I am starting to think they are different under the hood. Is there a way to replicate the remove function in Coq and if not, what alternative would you recommend?
Edit: I also want to keep the proof between In and In'. Originally I made In' a Type rather than a Prop, but that made the following proof fail with a type error.
Fixpoint In {A : Type} (x : A) (l : list A) : Prop :=
match l with
| [] ⇒ False
| x' :: l' ⇒ x' = x ∨ In x l'
end.
Theorem In_iff_In' :
forall {A : Type} (x : A) (l : list A),
In x l <-> In' x l.
Proof.
intros.
split.
- intros.
induction l.
+ inversion H.
+ simpl in H.
destruct H; subst.
* apply here. reflexivity.
* apply there. apply IHl. assumption.
- intros.
induction H.
+ left. subst. reflexivity.
+ right. assumption.
Qed.
In environment
A : Type
x : A
l : list A
The term "In' x l" has type "Type" while it is expected to have type
"Prop" (universe inconsistency).
The In here is from the Logic chapter of SF. I have a solution of the pigeonhole principle in Agda, so I want this bijection in order to convert to the form that the exercise asks.
Edit2:
Theorem remove_lemma :
forall {A} {x} {y} {l : list A} (pr : In' x l) (pr' : In' y l),
x = y \/ In' y (remove pr).
I also outright run into universe inconsistency in this definition even when using Type when defining In'.
You need to use an informative proof of membership. Right now, your Any takes values in Prop, which, due to its limitations on elimination (see the error message you got), is consistent with the axiom forall (P: Prop) (x y: P), x = y. This means that if you have some term that depends on a term whose type is in Prop (as is the case with remove), it has to only use the fact that such a term exists, not what term it is specifically. Generally, you can't use elimination (usually pattern matching) on a Prop to produce anything other than something that's also a Prop.
There are three essentially different proofs of In' 1 [1; 2; 1; 3; 1; 4], and, depending which proof is used, remove p might be [2; 1; 4; 1; 4], [1; 2; 3; 1; 4] or [1; 2; 1; 3; 4]. So the output depends on the specific proof in an essential way.
To fix this, you can simply replace the Prop in Inductive Any {A : Type} (P : A -> Type) : list A -> Prop with Type.1 Now we can eliminate into non-Prop types and your definition of remove works as written.
To answer your edits, I think the biggest issue is that some of your theorems/definitions need In' to be a Prop (because they depend on uninformative proofs) and others need the informative proof.
I think your best bet is to keep In' as a Type, but then prove uninformative versions of the theorems. In the standard libary, in Coq.Init.Logic, there is an inductive type inhabited.
Inductive inhabited (A: Type): Prop :=
| inhabits: A -> inhabited A.
This takes a type and essentially forgets anything specific about its terms, only remembering if it's inhabited or not. I think your theorem and lemma are provable if you simply replace In' x l with inhabited (In' x l). I was able to prove a variant of your theorem whose conclusion is simply In x l <-> inhabited (In' x l). Your proof mostly worked, but I had to use the following simple lemma in one step:
Lemma inhabited_there {A: Type} {P: A -> Type} {x: A} {xs: list A}:
inhabited (Any P xs) -> inhabited (Any P (x :: xs)).
Note: even though inhabited A is basically just a Prop version of A and we have A -> inhabited A, we can't prove inhabited A -> A in general because that would involve choosing an arbitrary element of A.2
I also suggested Set here before, but this doesn't work since the inductive type depends on A, which is in Type.
In fact, I believe that the proof assistant Lean uses something very similar to this for its axiom of choice.
Writing
Inductive Foo : Type -> Type :=
| foo : Foo Bar
with
Bar := .
gives
Error: Non strictly positive occurrence of "Bar" in "Foo Bar".
I know the standard example of why strict positivity is necessary; if I have
Inductive Fix :=
| fFix : (Fix -> Fix) -> Fix.
with an eliminator
Fix_rect : forall (P : Fix -> Type) (v : forall f, (forall x, P (f x)) -> P (fFix f)) (f : Fix), P f
then I can prove absurdity with
Fix_rect (fun _ => False) (fun f H => H (fFix id)) (fFix id) : False
(Aside: Does anything go wrong if instead the eliminator is
Fix_rect : forall (P : Fix -> Type) (v : forall f, (forall x, P x -> P (f x)) -> P (fFix f)) (f : Fix), P f
?)
However, I don't see a way to make use of occurrences that appear only in indices. Is there a way to derive a similar contradiction if non-strictly-positive occurrences are permitted in type indices?
This doesn't seem to be a positivity issue, contrary to the error message. Rather, since you have mutual indexing, this is an inductive-inductive type (a weird "large" one at that), which Coq doesn't support.
You could try defining non-indexed types, and separate recursively defined "well-formedness" relations which encode correct indexing. E. g.
Inductive PreFoo : Type :=
| foo : PreFoo.
Inductive Bar : Type :=.
Fixpoint FooWf (f : PreFoo) (t : Type) : Prop :=
match f with
| foo => (t = Bar)
end.
Definition Foo (t : Type) := sig (fun f => FooWf f t).
This is analogous to how you might have indexed intrinsic syntaxes for type theories or extrinsic presyntaxes with separate typing relations.
I'd like to define a predicate for list uniqueness and its decidability function in Coq. My first try was:
Section UNIQUE.
Variable A : Type.
Variable P : A -> Prop.
Variable PDec : forall (x : A), {P x} + {~ P x}.
Definition Unique (xs : list A) := exists! x, In x xs /\ P x.
Here I just have specified that predicate Unique xs will hold if there's just one value x in list xs such that P x holds. Now, comes the problem. When I've tried to define its Unique decidability:
Definition Unique_dec : forall xs, {Unique xs} + {~ Unique xs}.
induction xs ; unfold Unique in *.
+
right ; intro ; unfold unique in * ; simpl in * ; crush.
+
destruct IHxs ; destruct (PDec a).
destruct e as [y [Hiy HPy]].
...
I've got the following nasty error message:
Error: Case analysis on sort Set is not allowed for inductive definition ex.
I've googled this message and seen several similar problems in different contexts. At least to me, it seems that such problem is related to some restrictions on Coq pattern matching, right?
Now that the problem is settled, my questions:
1) All I want is to define a decidability for a uniqueness test based on a decidable predicate. In the standard library, there are similar tests for existencial and universal quantifiers. Both can be defined as inductive predicates. Is there a way to define "exists unique" as an inductive predicate on lists?
2) It is possible to define such predicate in order to it match the standard logic meaning of exists unique? Like exists! x, P x = exists x, P x /\ forall y, P y -> x = y?
What you're running into is that you can't pattern match on ex (the underlying inductive for both exists and exists!) in order to produce a value of type sumbool (the type for the {_} + {_} notation), which is a Type and not a Prop. The "nasty error message" isn't terribly helpful in figuring this out; see this bug report for a proposed fix.
To avoid this issue, I think you should prove a stronger version of Unique that produces something in Type (a sig) rather than Prop:
Definition Unique (xs : list A) := exists! x, In x xs /\ P x.
Definition UniqueT (xs : list A) := {x | unique (fun x => In x xs /\ P x) x}.
Theorem UniqueT_to_Unique : forall xs,
UniqueT xs -> Unique xs.
Proof.
unfold UniqueT, Unique; intros.
destruct X as [x H].
exists x; eauto.
Qed.
You can then prove decidability for this definition in Type, and from there prove your original statement if you want:
Definition UniqueT_dec : forall xs, UniqueT xs + (UniqueT xs -> False).
As mentioned in Anton's answer, this proof will require decidable equality for A, also in Type, namely forall (x y:A), {x=y} + {x<>y}.
Let me provide only a partial answer (it's too large for a comment).
If we go with this definition of uniqueness which admits multiple copies (as mentioned by Arthur), then Unique_dec implies decidability of equality for type A (as mentioned by #ejgallego).
Assuming we have
Unique_dec
: forall (A : Type) (P : A -> Prop),
(forall x : A, {P x} + {~ P x}) ->
forall xs : list A, {Unique P xs} + {~ Unique P xs}
We can show the following:
Lemma dec_eq A (a b : A) : a = b \/ a <> b.
Proof.
pose proof (Unique_dec (fun (_ : A) => True) (fun _ => left I) [a;b]) as U.
unfold Unique in U; destruct U as [u | nu].
- destruct u as (x & [I _] & U).
destruct I as [<- | [<- | contra]];
[specialize (U b) | specialize (U a) |]; firstorder.
- right; intros ->; apply nu; firstorder.
Qed.
Suppose I want an inductive definiton of a substring (with string being just a synonym for list).
Inductive substring {A : Set} (w : string A) :
(string A) -> Prop :=
| SS_substr : forall x y z : string A,
x ++ y ++ z = w ->
substring w y.
Here I can for example prove the following:
Theorem test : substring [3;4;1] [4].
Proof.
eapply SS_substr.
cbn.
instantiate (1:=[1]).
instantiate (1:=[3]).
reflexivity.
Qed.
However, the proof is "existential" rather than "universal", in spite of the fact that the inductive definition states forall x y z and only then constrains their shapes. This seems somewhat unintuitive to me. What gives?
Also, is it possible to make an inductive definition using exists x : string A, exists y : string A, exists z : string, x ++ y ++ z = w -> substring w y?
One important thing to note is that exists is not a built-in functionality of Coq (contrary to forall). Actually, exists itself is a notation, but behind there is an inductive type named ex. The notation and the inductive type are defined in the Coq standard library. Here is the definition of ex:
Inductive ex (A:Type) (P:A -> Prop) : Prop :=
ex_intro : forall x:A, P x -> ex (A:=A) P.
It is defined using one constructor and a universal quantification, like your substring type, so it is not surprising that your susbtring type seems to be "existential" at some point.
Of course, you can define your type using exists, and you do not even need Inductive.
Definition substring' {A : Set} (w y : string A) : Prop :=
exists x z, x ++ y ++ z = w.