What causes `fix` to appear after unfolding? - coq

After unfolding everything I can in an attempt to get rid of symbols I don't want in my induction hypothesis, I am left with:
X: Type
test: X -> bool
x: X
l: list X
IHl: (fix existsb
(X : Type) (test : X -> bool)
(l : list X) {struct l} : bool :=
fold orb (map test l) false) X test l =
negb
((fix forallb
(X : Type) (test : X -> bool)
(l : list X) {struct l} : bool :=
fold andb (map test l) true) X
(fun x : X => negb (test x)) l)
The two fixpoints which wind up embedded should be evaluated as far as I can see since I have already intros'ed their parameters; and if they simply were evaluated with their parameters, my IHl would be perfect.
I am not clear on why these won't evaluate in this case. As the example is from logical foundations, I haven't provided more of my solution hoping that it's enough to ask what tactic can I apply to IHl to cause coq to actually do the rewrite with the arguments that I am looking for.

I guess I don't really understand but it seems my case is fundamentally similar to this question:
Why cannot evaluate a fix-defined expression with an abstract value in Coq?
It seems that the workaround is to destruct l in order to ensure that the cases all start with a constructor, which then eliminates the fixpoints in two redundant cases that make the proof more or less immediate from there.
A post to enlighten me better about why there is no way to get one level of substitution here would be great, as I can't see any reason not to have a tactic that will apply in this circumstance.

Related

Define a polymorphic type in coq

So i was doing an exercise for learning coq. and I was trying to defind a type according to this encoding:
forall X.(X -> X) -> X -> X;`and this is from Alonzo Church(he proposed an encoding for natural number) as below:
0 , f:x:x
1 , f:x:fx
2 , f:x:f(fx)
3 , f:x:f(f(fx))
.....
n , f:x:fnx:
My code is like below:
Definition nat := forall X : Type, (X -> X) -> X -> X.
And the exercise require me to define expressions zero,one,two and three that encode the corresponding numbers as elements of nat:
Below is what I thought it will be
Definition zero : nat :=
fun (X : Type) (f : X -> X) (x : X) => x.
Definition one : nat :=
fun (X : Type) (f : X -> X) (x : X) => f x.
Definition two : nat :=
fun (X : Type) (f : X -> X) (x : X) => f (f x).
Definition three : nat :=
fun (X:Type)(f: X -> X)(x: X) => f ( f ( f x )).
My question is I need to prove that the plus n one = succ n. and the n is my defined type Nat
I have a succ function defined as below:
Definition succ (n : nat) : nat :=
fun (X : Type) (f : X -> X) (x : X) => f (n X f x).
my plus function defined as below:
Definition plus (n m : nat) : nat :=
fun (X : Type) (f : X -> X) (x : X) => (n X f (m X f x)).
The thing is when I tried to prove plus n one = succ n, I stuck in the middle and have no idea how to prove.
code as below:
Theorem plus_succ: forall (n : nat),
plus n one = succ n.
Proof.
intros.
1 subgoal
n : nat
______________________________________(1/1)
plus n one = succ n
and there's no way I can do inversion or any other tactic...(I am new to Coq, I've learnt list,poly,induction and tactics so far)
So that brings me to the thought that probably one, two or maybe all of my definition I defined above are not accurate.
Tons of appreciation if anyone can help me or give me some hints! Thankssss!
Using Church encodings in Coq is not a bad idea per-se, but you won't be able to say much about the inhabitants of this type (beside constructing some of them as you did).
The first issue is that inhabitants of this Church encoding are functions, and you will be able to show that two functions are equal in pure Coq only if they compute to the same value (up to unfolding, beta-reductions, reductions of match and fixes).
This is not the case for plus n one and succ n: you have on the lhs fun X f x => f (n X f x) and on the rhs fun X f x => n X f (f x). What you could hope to prove is forall (X : type) (f : X -> X) (x : X), f (n X f x) = n X f (f x), and you would then need to use functional extensionality, an axiom stating that the equality between functions is determined by the value of the functions at each point of their domain (see Coq.Logic.FunctionalExtensionality in the stdlib for more details on that point). This axiom is frequently assumed, but it is not innocent either (e.g. it does block computations).
The second issue you will run into is that you expect the inhabitants of nat = forall X, (X -> X) -> X -> X to be functions parametric in their first argument X : Type, but there is nothing actually enforcing that. Indeed, you can construct non-parametric inhabitants if you assume additional axioms, for instance excluded-middle. In pure Coq (without any axiom), there are results due to Bernardy and Lasson that show that indeed all inhabitants of your type nat are parametric, however you cannot internalize this result. And without parametricity, you have no bullets to prove equations such as f (n X f x) = n X f (f x).
So your troubles come from these two issues:
in absence of functional extensionality, the equalities that you can prove between functions are quite limited, and
you are not able in pure Coq to express internally that a quantification over types is parametric.
If you want to learn more about these issues on parametricity and what can still be achieved using Church encodings (or variants of these), I would recommend having a look at Chlipala's Parametric Higher-Order Abstract Syntax.

Make two arbitrary variables the same in Coq

I have the following coq code:
Theorem filter_exercise : forall (X : Type) (l lf : list X) (test : X -> bool)
(x : X),
filter test l = x :: lf ->
test x = true.
Proof.
intros X l lf test x eq.
induction l as [|l' l].
- inversion eq.
- inversion eq as [H].
Which gives me:
X : Type
l' : X
l, lf : list X
test : X -> bool
x : X
eq : filter test (l' :: l) = x :: lf
testEq : test x = false
IHl : filter test l = x :: lf -> false = true
============================
filter test l = (if test l' then l' :: filter test l else filter test l)
Here, if I could just say that because test x = false and both x and l' are universally quantified variables of type X, then I'd be done with the proof.
However, that's a semantic argument, and I'm not sure how to do that in Coq. Am I going down the wrong path?
EDIT
For posterity, this is the solution I ultimately obtained:
Theorem filter_exercise : forall (X : Type) (l lf : list X) (test : X -> bool)
(x : X),
filter test l = x :: lf ->
test x = true.
Proof.
intros X l lf test x eq.
induction l as [|l' l].
- inversion eq.
- simpl in eq. destruct (test l') eqn:testl'.
+ inversion eq. rewrite <- H0. apply testl'.
+ apply IHl. apply eq.
Qed.
I am not sure what you mean by "semantic argument", but this proof strategy is not correct, neither on paper nor in Coq. Consider, for instance, the following statement:
Lemma faulty : forall n m : nat, even n -> even m.
Proof. Admitted.
By your logic, if n is even, then m should also be even, since both are universally quantified variables of type nat. However, precisely because they are universally quantified, they can instantiated to different values of nat, thus yielding obviously contradictory statements. For instance, if we instantiate faulty with 2 and 1, we should be able to conclude that 1 is even, which is not true.
Your argument that test x = false -> test l' = false is not true, as both variables x and l are universally quantified, and thus can have any value. You could just have a specific relationship between both variables in your hypothesis, but here it is not the case, except the relationship filter test (l' :: l) = x :: lf, that tells you that x could be an element of l which has not been filtered by test (but it also might be l').
You should not use inversion here, as your problem is really simple. You idea to perform an induction is fine however :
Try first to simplify several hypothesis.
Then see if there are different cases to deal with, and use destruct when needed (on the value of test l' in this problem)
You should be able to solve the problem then (the most complicated tactic you might have to use is injection)

Coq - undocumented error on induction with eqn:

Using Coq 8.4pl3, I'm getting an error on induction with the eqn: variant that is not listed under induction in the reference manual.
(* Export below requires Software Foundations 4.0. *)
Require Export Logic.
Inductive disjoint (X : Type) (l1 l2 : list X) : Prop :=
| nil1 : l1 = [] -> disjoint X l1 l2
| nil2 : l2 = [] -> disjoint X l1 l2
| bothCons : forall x:X,
In x l1 ->
not (In x l2) ->
disjoint X l1 l2.
Fixpoint head (X : Type) (l : list X) : option X :=
match l with
| [] => None
| h :: t => Some h
end.
Fixpoint tail (X : Type) (l : list X) : list X :=
match l with
| [] => []
| h :: t => t
end.
Inductive NoDup (X : Type) (l : list X) : Prop :=
| ndNil : l = [] -> NoDup X l
| ndSingle : forall x:X, l = [x] -> NoDup X l
| ndCons : forall x:X, head X l = Some x ->
not (In x (tail X l)) /\ NoDup X (tail X l) ->
NoDup X l.
Theorem disjoint__app_NoDup :
forall (X : Type) (l1 l2 : list X),
disjoint X l1 l2 /\ NoDup X l1 /\ NoDup X l2 ->
NoDup X (l1 ++ l2).
Proof.
intros. induction H eqn:caseEqn.
If I substitute just plain "induction H" for the last step, I get no error, but with the above eqn: argument, I get the error:
Error: a is used in conclusion.
(Previously there was a condition missing in the theorem statement, and the same error listed an identifier d instead.)
Ref manual lists "is used in conclusion" as an error from use of assert. It makes some kind of sense that behind the scenes, eqn: might be generating assertions, but I have no identifier a visible in the context, and I can't see what Coq is trying to automatically do with it.
Tried replacing beginning of the proof with
intros. remember H. induction H.
Now the attempt to do induction gives the same error as before, only with H instead of a. (When the theorem was missing the additional condition, Coq also explicitly added a d to the context, identical to the hypothesis H.)
How can I move forward here? I'm trying to avoid losing information from the context.
This is a minor bug; I've reported it. However, the thing you are trying to do here is not particularly sensible. Note that you are invoking induction on a conjunction (/\), and asking Coq to leave you an equation that says that the original hypothesis is equal to the conjunction of the two generated proofs. There are two issues here:
Your hypothesis is not used in a dependent fashion anywhere, so you don't need to remember it.
Your hypothesis is not recursive, so you could just as well do destruct H rather than induction H.
As for the error message, it becomes a bit more clear if you note that replacing /\ with * makes induction H eqn:caseEqn go through, and breaks your hypothesis apart into two parts named a and b. The actual issue is that the proof term constructed by induction H eqn:... is ill-typed when H's type is a Prop, because you cannot eliminate Props to get information. I suspect that the code simply tries to do something with the a that it creates in a particular way, and assumes that any failure to do that must be because a is used in the conclusion, rather than because the proof term it was creating was ill-formed.

Prove "rev (rev l) = l" in Coq

This is one of the exercise given to me, I got stuck almost immediately after doing an induction on l. I dont know what other assertion to make here.
I'm not allowed to use advanced tactics like auto, intuition etc.
Fixpoint snoc {A : Type} l a : list A :=
match l with
| nil => a :: nil
| h :: t => h :: (snoc t a)
end.
Fixpoint rev {A : Type} l : list A :=
match l with
| nil => nil
| h :: t => snoc (rev t) h
end.
(Prove the following)
Theorem rev_rev : forall A (l : list A),
rev (rev l) = l.
We have all been new to this, and in the beginning it is useful to get help to not get stuck an lose courage when trying to master a new subject. I'll try to give you a hint without giving away too much.
The reason why this is trickier than earlier exercises may be because this proof involves doing two inductive reasoning steps. You probably did the first one just fine and got the second goal like
...
IHl : rev (rev l) = l
============================
rev (snoc (rev l) a) = a :: l
Unfortunately you can't use your inductive hypothesis IHl immediately, because the argument to rev is not in the right shape.
So, here you could try to prove another lemma about rev (snoc l a) = ... that would turn the goal into something which you could rewrite with IHl.
If you can figure that out, and prove that in a lemma, then you should be fine.
We won't do your homework for you, you should first prove it on pen & paper as #gallais said.
A tip: you might need to generalize your property a little (use an intermediate lemma) to be able to prove rev_rev. You should have a look at rev_append.

Recursive function definition in coq with limit on set of possible inputs

I need to define a recursive function with no easily measurable argument. I keep a list of used arguments to ensure that each one is used at most once, and the input space is finite.
Using a measure (inpspacesize - (length l)) works mostly, but I get stuck in one case. It seems I'm missing the information that previous layers of l have been constructed correctly, i. e. there are no duplicates and all entries are really from the input space.
Now I'm searching for a list replacement that does what I need.
Edit I've reduced this to the following now:
I have nats smaller than a given max and need to ensure that the function is called at most once for every number. I've come up with the following:
(* the condition imposed *)
Inductive limited_unique_list (max : nat) : list nat -> Prop :=
| LUNil : limited_unique_list max nil
| LUCons : forall x xs, limited_unique_list max xs
-> x <= max
-> ~ (In x xs)
-> limited_unique_list max (x :: xs).
(* same as function *)
Fixpoint is_lulist (max : nat) (xs0 : list nat) : bool :=
match xs0 with
| nil => true
| (x::xs) => if (existsb (beq_nat x) xs) || negb (leb x max)
then false
else is_lulist max xs
end.
(* really equivalent *)
Theorem is_lulist_iff_limited_unique_list : forall (max:nat) (xs0 : list nat),
true = is_lulist max xs0 <-> limited_unique_list max xs0.
Proof. ... Qed.
(* used in the recursive function's step *)
Definition lucons {max : nat} (x : nat) (xs : list nat) : option (list nat) :=
if is_lulist max (x::xs)
then Some (x :: xs)
else None.
(* equivalent to constructor *)
Theorem lucons_iff_LUCons : forall max x xs, limited_unique_list max xs ->
(#lucons max x xs = Some (x :: xs) <-> limited_unique_list max (x::xs)).
Proof. ... Qed.
(* unfolding one step *)
Theorem lucons_step : forall max x xs v, #lucons max x xs = v ->
(v = Some (x :: xs) /\ x <= max /\ ~ (In x xs)) \/ (v = None).
Proof. ... Qed.
(* upper limit *)
Theorem lucons_toobig : forall max x xs, max < x
-> ~ limited_unique_list max (x::xs).
Proof. ... Qed.
(* for induction: increasing max is ok *)
Theorem limited_unique_list_increasemax : forall max xs,
limited_unique_list max xs -> limited_unique_list (S max) xs.
Proof. ... Qed.
I keep getting stuck when trying to prove inductively that I cannot insert an element into the full list (either the IH comes out unusable or I can't find the information I need). As I think this non-insertability is crucial for showing termination, I've still not found a working solution.
Any suggestions on how to prove this differently, or on restructuring the above?
Hard to say much without more details (please elaborate!), but:
Are you using the Program command? It's certainly very helpful for defining functions with non-trivial measures.
For uniqueness wouldn't it work if you tried sets? I remember writing ones a function that sounds very much like what you are saying: I had a function for which an argument contained a set of items. This set of items was growing monotonously and was limited to a finite space of items, giving the termination argument.