How to implement remove with a membership proof as an argument in Coq? - coq

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.

Related

Understanding specialize tactic

Trying to comprehend the answer of #keep_learning I walked through this code step by step:
Inductive nostutter {X:Type} : list X -> Prop :=
| ns_nil : nostutter []
| ns_one : forall (x : X), nostutter [x]
| ns_cons: forall (x : X) (h : X) (t : list X), nostutter (h::t) -> x <> h -> nostutter (x::h::t).
Example test_nostutter_4: not (nostutter [3;1;1;4]).
Proof.
intro.
inversion_clear H.
inversion_clear H0.
unfold not in H2.
(* We are here *)
specialize (H2 eq_refl).
apply H2.
Qed.
Here is what we have before excuting specialize
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
============================
False
Here is eq Prop whose constructor eq_refl is used in specialize:
Inductive eq (A:Type) (x:A) : A -> Prop :=
eq_refl : x = x :>A
where "x = y :> A" := (#eq A x y) : type_scope.
I can't explain, how this command works:
specialize (H2 eq_refl).
I read about specialize in reference manual, but the explanation there is too broad. As far as I understand it sees that "1 = 1" expression in H2 satisfies eq_refl constructor and therefore eq proposition is True. Then it simplifies the expression:
True -> False => False
And we get
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : False
============================
False
Can somebody provide me a minimal example with explanation of what is specialize doing, so I could freely use it?
Update
Trying to imitate how specialize works using apply I did the following:
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
apply H in a.
This gives:
A : Type
B : Type
H : A -> B
a : B
============================
B
Almost the same as specialize, only different hypothesis name.
In test_nostutter_4 theorem I tried this and it worked:
remember (#eq_refl nat 1) as Heq.
apply H2 in Heq as H3.
It gives us:
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
Heq : 1 = 1
H3 : False
HeqHeq : Heq = eq_refl
============================
False
This one was more complex, we had to introduce a new hypothesis Heq. But we got what we need - H3 at the end.
Does specialize internally use something like remember? Or is it possible to solve it with apply but without remember?
specialize, in its simplest form, simply replaces a given hypothesis with that hypothesis applied to some other term.
In this proof,
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
specialize (H a).
exact H.
Qed.
we initially have the hypothesis H: A -> B. When we call specialize (H a), we apply H to a (apply as in function application). This gives us something of type B. specialize then gets rid of the old H for us and replaces it with the result of the application. It gives the new hypothesis the same name: H.
In your case, we have H2: 1 = 1 -> False, which is a function from the type 1 = 1 to the type False. That means that H2 applied to eq_refl is of type False, i.e. H2 eq_refl: False. When we use the tactic specialize (H2 eq_refl)., the old H2 is cleared and replaced by a new term (H2 eq_refl) whose type is False. It keeps the old name H2, though.
specialize is useful when you're sure that you're only going to use a hypothesis once, since it automatically gets rid of the old hypothesis. One disadvantage is that the old name may not fit the meaning of the new hypothesis. However, in your case and in my example, H is a generic enough name that it works either way.
To your update...
specialize is a core tactic defined directly in the ltac plugin. It doesn't use any other tactic internally, since it is its internals.
If you want to keep a hypothesis, you can use the as modifier, which works for both specialize and apply. In the proof
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
if you do specialize (H a) as H0., instead of clearing H, it'll introduce a new hypothesis H0: B. apply H in a as H0. has the same effect.

Coq: How to produce a strong polymorphic dependent type hypothesis

I have been having some problems with dependent induction because a "weak hypothesis".
For example :
I have a dependent complete foldable list :
Inductive list (A : Type) (f : A -> A -> A) : A -> Type :=
|Acons : forall {x x'' : A} (y' : A) (cons' : list f (f x x'')), list f (f (f x x'') y')
|Anil : forall (x: A) (y : A), list f (f x y).
And a function that a return the applied fold value from inductive type list and other function that forces a computation of these values through a matching.
Definition v'_list {X} {f : X -> X -> X} {y : X} (A : list f y) := y.
Fixpoint fold {A : Type} {Y : A} (z : A -> A -> A) (d' : list z Y) :=
match d' return A with
|Acons x y => z x (#fold _ _ z y)
|Anil _ x y => z x y
end.
Clearly, that's function return the same value if have the same dependent typed list and prove this don't should be so hard.
Theorem listFold_eq : forall {A : Type} {Y : A} (z : A -> A -> A) (d' : list z Y), fold d' = v'_list d'.
intros.
generalize dependent Y.
dependent induction d'.
(.. so ..)
Qed.
My problem is that dependent definition generates for me a weak hypothesis.
Because i have something like that in the most proof that i use dependent definitions, the problem of proof above:
A : Type
z : A -> A -> A
x, x'', y' : A
d' : list z (z x x'')
IHd' : fold d' = v'_list d'
______________________________________(1/2)
fold (Acons y' d') = v'_list (Acons y' d')
Even i have a polymorphic definition in (z x x'') i can't apply IHd' in my goal.
My question if have a way of define more "powerful" and polymorphic induction, instead of working crazy rewriting terms that sometimes struggling me.
If you do
simpl.
unfold v'_list.
You can see that you're almost there (you can finish with rewriting), but the arguments of z are in the wrong order, because list and fold don't agree on the way the fold should go.
On an unrelated note, Acons could quantify over a single x, replacing f x x'' with just x.

List uniqueness predicate decidability

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.

Proof of the application of a Substitution on a term

I am trying to proof that the application of an empty Substitution on a term is equal to the given term.
Here is the code:
Require Import Coq.Strings.String.
Require Import Coq.Lists.List.
Require Import Coq.Arith.EqNat.
Require Import Recdef.
Require Import Omega.
Import ListNotations.
Set Implicit Arguments.
Inductive Term : Type :=
| Var : nat -> Term
| Fun : string -> list Term -> Term.
Definition Subst : Type := list (nat*Term).
Definition maybe{X Y: Type} (x : X) (f : Y -> X) (o : option Y): X :=
match o with
|None => x
|Some a => f a
end.
Fixpoint lookup {A B : Type} (eqA : A -> A -> bool) (kvs : list (A * B)) (k : A) : option B :=
match kvs with
|[] => None
|(x,y) :: xs => if eqA k x then Some y else lookup eqA xs k
end.
I am trying to proof some properties of this function.
Fixpoint apply (s : Subst) (t : Term) : Term :=
match t with
| Var x => maybe (Var x) id (lookup beq_nat s x )
| Fun f ts => Fun f (map (apply s ) ts)
end.
Lemma empty_apply_on_term:
forall t, apply [] t = t.
Proof.
intros.
induction t.
reflexivity.
I am stuck after the reflexivity. I wanted to do induction on the list build in a term but if i do so i'ĺl get stuck in a loop.
i will appreciate any help.
The problem is that the automatically generated inductive principle for the Term type is too weak, because it has another inductive type list inside it (specifically, list is applied to the very type being constructed). Adam Chlipala's CPDT gives a good explanation of what's going on, as well as an example of how to manually build a better inductive principle for such types in the inductive types chapter. I've adapted his example nat_tree_ind' principle for your Term inductive, using the builtin Forall rather than a custom definition. With it, your theorem becomes easy to prove:
Section Term_ind'.
Variable P : Term -> Prop.
Hypothesis Var_case : forall (n:nat), P (Var n).
Hypothesis Fun_case : forall (s : string) (ls : list Term),
Forall P ls -> P (Fun s ls).
Fixpoint Term_ind' (tr : Term) : P tr :=
match tr with
| Var n => Var_case n
| Fun s ls =>
Fun_case s
((fix list_Term_ind (ls : list Term) : Forall P ls :=
match ls with
| [] => Forall_nil _
| tr'::rest => Forall_cons tr' (Term_ind' tr') (list_Term_ind rest)
end) ls)
end.
End Term_ind'.
Lemma empty_apply_on_term:
forall t, apply [] t = t.
Proof.
intros.
induction t using Term_ind'; simpl; auto.
f_equal.
induction H; simpl; auto.
congruence.
Qed.
This is a typical trap for beginners. The problem is that your definition of Term has a recursive occurrence inside another inductive type -- in this case, list. Coq does not generate a useful inductive principle for such types, unfortunately; you have to program your own. Adam Chlipala's CDPT has a chapter on inductive types that describes the problem. Just look for "nested inductive types".

Ltac-tically abstracting over a subterm of the goal type

As a rough and untutored background, in HoTT, one deduces the heck out of the inductively defined type
Inductive paths {X : Type } : X -> X -> Type :=
| idpath : forall x: X, paths x x.
which allows the very general construction
Lemma transport {X : Type } (P : X -> Type ){ x y : X} (γ : paths x y):
P x -> P y.
Proof.
induction γ.
exact (fun a => a).
Defined.
The Lemma transport would be at the heart of HoTT "replace" or "rewrite" tactics; the trick, so far as I understand it, would be, supposing a goal which you or I can abstractly recognize as
...
H : paths x y
[ Q : (G x) ]
_____________
(G y)
to figure out what is the necessary dependent type G, so that we can apply (transport G H). So far, all I've figured out is that
Ltac transport_along γ :=
match (type of γ) with
| ?a ~~> ?b =>
match goal with
|- ?F b => apply (transport F γ)
| _ => idtac "apparently couldn't abstract" b "from the goal." end
| _ => idtac "Are you sure" γ "is a path?" end.
isn't general enough. That is, the first idtac gets used rather often.
The question is
[Is there a | what is the] Right Thing to Do?
There is a bug about using rewrite for relations in type, which would allow you to just say rewrite <- y.
In the mean time,
Ltac transport_along γ :=
match (type of γ) with
| ?a ~~> ?b => pattern b; apply (transport _ y)
| _ => idtac "Are you sure" γ "is a path?"
end.
probably does what you want.
The feature request mentioned by Tom Prince in his answer has been granted:
Require Import Coq.Setoids.Setoid Coq.Classes.CMorphisms.
Inductive paths {X : Type } : X -> X -> Type :=
| idpath : forall x: X, paths x x.
Lemma transport {X : Type } (P : X -> Type ){ x y : X} (γ : paths x y):
P x -> P y.
Proof.
induction γ.
exact (fun a => a).
Defined.
Global Instance paths_Reflexive {A} : Reflexive (#paths A) := idpath.
Global Instance paths_Symmetric {A} : Symmetric (#paths A).
Proof. intros ?? []; constructor. Defined.
Global Instance proper_paths {A} (x : A) : Proper paths x := idpath x.
Global Instance paths_subrelation
(A : Type) (R : crelation A)
{RR : Reflexive R}
: subrelation paths R.
Proof.
intros ?? p.
apply (transport _ p), RR.
Defined.
Global Instance reflexive_paths_dom_reflexive
{B} {R' : crelation B} {RR' : Reflexive R'}
{A : Type}
: Reflexive (#paths A ==> R')%signature.
Proof. intros ??? []; apply RR'. Defined.
Goal forall (x y : nat) G, paths x y -> G x -> G y.
intros x y G H Q.
rewrite <- H.
exact Q.
Qed.
I found the required instances by comparing the logs I got with Set Typeclasses Debug from setoid_rewrite <- H when H : paths x y and when H : eq x y.