Error message: Not the right number of missing arguments (expected 1) - coq

I faced error message when running the following code.
Require Import Coq.Lists.List.
Import ListNotations.
Theorem con_not_com :
exists A (l1 l2 : list A), l1 ++ l2 <> l2 ++ l1.
Proof.
exists bool [true] [false].
I'm wondering how I can solve it. Thanks.

You need commas:
Require Import Coq.Lists.List.
Import ListNotations.
Theorem con_not_com :
exists A (l1 l2 : list A), l1 ++ l2 <> l2 ++ l1.
Proof.
exists bool, [true], [false].

Related

Stuck on Coq proof with list induction

I'm finding myself stuck on a Coq proof.
Preliminary definitions:
Require Import Coq.Bool.Bool.
Require Import Coq.Arith.Arith.
Require Import Coq.Arith.EqNat.
Require Import Coq.omega.Omega.
Require Import Coq.Lists.List.
Require Export Coq.Strings.String.
Import ListNotations.
Definition total_map (A:Type) := string -> A.
Definition state := total_map nat.
Inductive sinstr : Type :=
| SPush : nat -> sinstr
| SLoad : string -> sinstr
| SPlus : sinstr
| SMinus : sinstr
| SMult : sinstr.
Definition s_execute_instr (st : state) (stack : list nat)
(instr : sinstr)
: option (list nat) :=
match instr with
| SPush n => Some (n :: stack)
| SLoad x => Some (st x :: stack)
| SPlus => match stack with
| x :: y :: stack' => Some (x+y :: stack')
| _ => None
end
| SMinus => match stack with
| x :: y :: stack' => Some (y-x :: stack')
| _ => None
end
| SMult => match stack with
| x :: y :: stack' => Some (x*y::stack')
| _ => None
end
end.
Fixpoint s_execute (st : state) (stack : list nat)
(prog : list sinstr)
: option (list nat) :=
match prog with
| [] => Some (stack)
| instr::prog' => match (s_execute_instr st stack instr) with
| Some stack' => s_execute st stack' prog'
| None => None
end
end.
And my attempt at a theorem proof:
Theorem s_execute_relational : forall (l1 l2: list sinstr) (sk sk': list nat) (st : state),
s_execute st sk l1 = Some sk' ->
s_execute st sk (l1 ++ l2) = s_execute st sk' l2.
Proof.
intros l1 l2 sk sk' st H.
induction l1 as [|l1' l1].
- inversion H. reflexivity.
-
The current status is:
l1' : sinstr
l1, l2 : list sinstr
sk, sk' : list nat
st : state
H : s_execute st sk (l1' :: l1) = Some sk'
IHl1 : s_execute st sk l1 = Some sk' -> s_execute st sk (l1 ++ l2) = s_execute st sk' l2
============================
s_execute st sk ((l1' :: l1) ++ l2) = s_execute st sk' l2
I've gone this path because I think I need to use induction somehow, but at this point, I'm not sure how to proceed.
I tried induction on l2 as well, but that doesn't seem to get me anywhere, either;
Theorem s_execute_relational : forall (l1 l2: list sinstr) (sk sk': list nat) (st : state),
s_execute st sk l1 = Some sk' ->
s_execute st sk (l1 ++ l2) = s_execute st sk' l2.
Proof.
intros l1 l2 sk sk' st H.
induction l2 as [|l2' l2].
- simpl. rewrite <- H. replace (l1 ++ []) with l1.
+ reflexivity.
+ symmetry. apply app_nil_r.
-
l1 : list sinstr
l2' : sinstr
l2 : list sinstr
sk, sk' : list nat
st : state
H : s_execute st sk l1 = Some sk'
IHl2 : s_execute st sk (l1 ++ l2) = s_execute st sk' l2
============================
s_execute st sk (l1 ++ l2' :: l2) =
s_execute st sk' (l2' :: l2)
It's strange asking this type of question on SO because it's not...really a reusable question/title is bad, but unsure how to improve on that front, either.
you should not introduce all variables as you do in the first line. You should first look at your recursive functions and has yourself two questions:
What are the recursive functions and their "structurally recursive arguments" here. You may have noticed that when Coq accepts a recursive definition, it tells you with respect to which argument it is structurally recursive.
What happens to the arguments that are not structurally recursives in the function: do they change between the recursive call or not?
Answer to question 1:
In your case, we have two main recursive functions List.app and s_execute. The recursive argument to s_execute is l1 on the left hand side of the implication. The recursive argument to s_execute is l1 ++ l2 in the left-hand side of the final equality, and the recursive argument to s_execute is only l2 in the right hand side. Because l1 ++ l2 is in position of a recursive argument, we can now look at the recursive argument of app by looking at its code, and we see that the argument that decreases structurally at the recursive call is again l1. This gives a strong feeling that induction should be performed on l1.
Answer to question 2:
s_execute takes three arguments. The state does not change during execution, but the stack does. So you can fix st for the whole proof, but the stack argument should not be fixed. A similar observation appears for app: the second argument does not change during recursive calls.
Practically, you can start your proof with
intros l1 l2.
induction l1 ....
Don't go any further in the intros, because the stack should be left flexible, you will need this flexibility when using the induction hypothesis.
Just for the fun, you can try introducing more arguments, but you have to free the flexible ones by using the revert tactic. Just like so:
intros l1 l2 sk sk' st; revert sk.
induction l1 as ....
Here only sk has to be freed (or unfixed, or reverted).
This is actually a very good question, and the need to avoid fixing arguments that will need to change in uses of the induction hypothesis pops up regularly in formal proofs.
Later edit
Here is how I started your proof:
Theorem s_execute_relational : forall (l1 l2: list sinstr) (sk sk': list nat) (st : state),
s_execute st sk l1 = Some sk' ->
s_execute st sk (l1 ++ l2) = s_execute st sk' l2.
Proof.
intros l1 l2 sk sk' st; revert sk.
induction l1 as [ | n l1 Ih].
simpl; intros sk [= skk']; rewrite skk'; easy.
Now we are in the induction step case. The stack is still universally quantified in the goal's conclusion. So the induction hypothesis and the goal are actually talking about two potentially different stacks. The next step is to fix an arbitrary stack to reason on the conclusion.
intros sk.
Then we compute,
simpl.
We are reasoning about a symbolic execution of the code, and we don't know how (s_execute_instr st sk n) will result, so we need to cover both cases, this is what the destruct step does.
destruct (s_execute_instr st sk n) as [sk1 | ].
In the first case (for the execution of (s_execute_instr st sk n)), a new state sk1 appears, on which execution will proceed, and we know that
execution of l1 from that state leads exactly to Some sk'. Let's give the name complete_l1 to that new state. Now it happens that the proof can be finished by instantiating the induction hypothesis on this new state.
intros complete_l1.
now rewrite (Ih sk1).
There remain the other case produced by the destruct step, but this case contains a self-inconsistent assumption of the form None = Some sk'. The easy tactic knows how to get rid of this (actually easy relies on discriminate, which implements what I like to call the non-confusion property of data-types).
easy.
Qed.
Please tell me what was missing in your attempt? Was it the destruct step?
Eventually, I figured it out.
Theorem s_execute_relational : forall (l1 l2: list sinstr) (sk sk': list nat) (st : state),
s_execute st sk l1 = Some sk' ->
s_execute st sk (l1 ++ l2) = s_execute st sk' l2.
Proof.
intros l1.
induction l1 as [| l1' l1].
- intros l2 sk sk' st H. simpl.
inversion H. reflexivity.
- intros l2 sk sk' st H.
assert (forall (x:sinstr) (xs ys: list sinstr), (x::xs) ++ys = x::(xs++ys)) as app_comm_cons.
{
auto.
}
rewrite app_comm_cons.
unfold s_execute in *. destruct (s_execute_instr st sk l1').
+ eapply IHl1. apply H.
+ inversion H.
Qed.

Prove equality of lists with list_beq

list_beq is generated by Scheme Equality for list..
I'm sure that l = v if list_beq A eq l v holds and want to prove it.
But, we can't proof that unless A and eq are not concrete.
So, I want to proof that when A = nat eq = Nat.eqb.
Require Import Coq.Lists.List.
Import ListNotations.
From mathcomp Require Import ssreflect.
Scheme Equality for list.
Lemma list_eq (l v:list nat) : list_beq nat Nat.eqb l v = true -> l = v.
Proof.
case: l.
remember (list_beq nat Nat.eqb [] []).
destruct b;last first.
inversion Heqb.
destruct v => //.
intros.
destruct v => //.
rewrite /list_beq in H.
Abort.
I don't know how to do any more.
Please tell me how to do that.
I think one reason for/benefit of using Schemes is to not have to do the induction and go through all the cases yourself.
If you search for list_beq that was generated by Scheme you find the generated lemma internal_list_dec_bl that can help you to reason about the absurd case you get when reasoning about list_eq_dec.
Require Import List. Import ListNotations.
Scheme Equality for list.
Lemma list_eq (l v:list nat) : list_beq nat Nat.eqb l v = true -> l = v.
destruct(list_eq_dec _ PeanoNat.Nat.eqb) with l v as [H|H];
intros; try apply PeanoNat.Nat.eqb_eq in H. trivial. trivial. trivial.
exfalso.
apply H. apply internal_list_dec_bl with Nat.eqb.
apply PeanoNat.Nat.eqb_eq. apply H0.
Qed.
I have proved on my own.
Require Import Coq.Lists.List Coq.Bool.Bool.
Import ListNotations.
Scheme Equality for list.
From mathcomp Require Import ssreflect.
Lemma list_eq (l v:list nat) : list_beq nat Nat.eqb l v = true -> l = v.
Proof.
- elim: l v.
remember (list_beq nat Nat.eqb [] []).
destruct b;last first.
inversion Heqb.
destruct v => //.
- intros.
destruct v => //.
rewrite /= in H0.
apply andb_true_iff in H0.
move: H0 => [left right].
f_equal.
apply PeanoNat.Nat.eqb_eq in left.
apply left.
apply H in right.
apply right.
Qed.

Teach coq to check termination

Coq, unlike many others, accepts an optional explicit parameter,which can be used to indicate the decreasing structure of a fixpoint definition.
From Gallina specification, 1.3.4,
Fixpoint ident params {struct ident0 } : type0 := term0
defines the syntax. but from it, we've known that it must be an identifier, instead of a general measure.
However, in general, there are recursive functions, that the termination is not quite obvious,or it in fact is, but just difficult for the termination checker to find a decreasing structure. For example, following program interleaves two lists,
Fixpoint interleave (A : Set) (l1 l2 : list A) : list A :=
match l1 with
| [] => []
| h :: t => h :: interleave l2 t
end
This function clearly terminates, while Coq just couldn't figure it out. The reason is neither l1 nor l2 are decreasing every cycle. But what if we consider a measure, defined to be length l1 + length l2? Then this measure clearly decreases every recursion.
So my question is, in the case of sophisticated situation, where code is not straightforward to be organized in a termination checkable way, how do you educate coq and convince it to accept the fixpoint definition?
You have multiple options and all of them boil down to structural recursion in the end.
Preamble
From Coq Require Import List.
Import ListNotations.
Set Implicit Arguments.
Structural recursion
Sometimes you can reformulate your algorithm in a structurally recursive way:
Fixpoint interleave1 {A} (l1 l2 : list A) {struct l1} : list A :=
match l1, l2 with
| [], _ => l2
| _, [] => l1
| h1 :: t1, h2 :: t2 => h1 :: h2 :: interleave1 t1 t2
end.
Incidentally, in some cases you can use a trick with nested fixes -- see this definition of Ackermann function (it wouldn't work with just Fixpoint).
Program Fixpoint
You can use Program Fixpoint mechanism which lets you write your program naturally and later prove that it always terminates.
From Coq Require Import Program Arith.
Program Fixpoint interleave2 {A} (l1 l2 : list A)
{measure (length l1 + length l2)} : list A :=
match l1 with
| [] => l2
| h :: t => h :: interleave2 l2 t
end.
Next Obligation. simpl; rewrite Nat.add_comm; trivial with arith. Qed.
Function
Another option is to use the Function command which can be somewhat limited compared to Program Fixpoint. You can find out more about their differences here.
From Coq Require Recdef.
Definition sum_len {A} (ls : (list A * list A)) : nat :=
length (fst ls) + length (snd ls).
Function interleave3 {A} (ls : (list A * list A))
{measure sum_len ls} : list A :=
match ls with
| ([], _) => []
| (h :: t, l2) => h :: interleave3 (l2, t)
end.
Proof.
intros A ls l1 l2 h t -> ->; unfold sum_len; simpl; rewrite Nat.add_comm; trivial with arith.
Defined.
Equations plugin
This is an external plugin which addresses many issues with defining functions in Coq, including dependent types and termination.
From Equations Require Import Equations.
Equations interleave4 {A} (l1 l2 : list A) : list A :=
interleave4 l1 l2 by rec (length l1 + length l2) lt :=
interleave4 nil l2 := l2;
interleave4 (cons h t) l2 := cons h (interleave4 l2 t).
Next Obligation. rewrite Nat.add_comm; trivial with arith. Qed.
The code above works if you apply this fix.
Fix / Fix_F_2 combinators
You can learn more about this (manual) approach if you follow the links from this question about mergeSort function. By the way, the mergeSort function can be defined without using Fix if you apply the nested fix trick I mentioned earlier. Here is a solution which uses Fix_F_2 combinator since we have two arguments and not one like mergeSort:
Definition ordering {A} (l1 l2 : list A * list A) : Prop :=
length (fst l1) + length (snd l1) < length (fst l2) + length (snd l2).
Lemma ordering_wf' {A} : forall (m : nat) (p : list A * list A),
length (fst p) + length (snd p) <= m -> Acc (#ordering A) p.
Proof.
unfold ordering; induction m; intros p H; constructor; intros p'.
- apply Nat.le_0_r, Nat.eq_add_0 in H as [-> ->].
intros contra%Nat.nlt_0_r; contradiction.
- intros H'; eapply IHm, Nat.lt_succ_r, Nat.lt_le_trans; eauto.
Defined.
Lemma ordering_wf {A} : well_founded (#ordering A).
Proof. now red; intro ; eapply ordering_wf'. Defined.
(* it's in the stdlib but unfortunately opaque -- this blocks evaluation *)
Lemma destruct_list {A} (l : list A) :
{ x:A & {tl:list A | l = x::tl} } + { l = [] }.
Proof.
induction l as [|h tl]; [right | left]; trivial.
exists h, tl; reflexivity.
Defined.
Definition interleave5 {A} (xs ys : list A) : list A.
refine (Fix_F_2 (fun _ _ => list A)
(fun (l1 l2 : list A)
(interleave : (forall l1' l2', ordering (l1', l2') (l1, l2) -> list A)) =>
match destruct_list l1 with
| inright _ => l2
| inleft pf => let '(existT _ h (exist _ tl eq)) := pf in
h :: interleave l2 tl _
end) (ordering_wf (xs,ys))).
Proof. unfold ordering; rewrite eq, Nat.add_comm; auto.
Defined.
Evaluation tests
Check eq_refl : interleave1 [1;2;3] [4;5;6] = [1;4;2;5;3;6].
Check eq_refl : interleave2 [1;2;3] [4;5;6] = [1;4;2;5;3;6].
Check eq_refl : interleave3 ([1;2;3], [4;5;6]) = [1;4;2;5;3;6].
Fail Check eq_refl : interleave4 [1;2;3] [4;5;6] = [1;4;2;5;3;6]. (* Equations plugin *)
Check eq_refl : interleave5 [1;2;3] [4;5;6] = [1;4;2;5;3;6].
Exercise: what happens with this last check if you comment out destruct_list lemma?
You can use something called a measure instead of a structural argument for termination. For this, I believe you have to use the Program Fixpoint mechanism, which is a little involved and will make your proofs look uglier (because it generates a structural recursion out of the proof that you provide, so that the function you will actually use is not quite the function you wrote).
Details here:
https://coq.inria.fr/refman/program.html
It also seems like something called Equations can deal with measures?
cf. http://mattam82.github.io/Coq-Equations/examples/RoseTree.html
https://www.irif.fr/~sozeau/research/coq/equations.en.html

Coq not generating inductive hypothesis

I was given a solution to the following theorem as shown below:
Require Import Coq.Lists.List.
Import ListNotations.
Inductive suffix {X : Type} : list X -> list X -> Prop :=
| suffix_end : forall xs,
suffix xs xs
| suffix_step : forall x xs ys,
suffix xs ys ->
suffix (x :: xs) ys.
Theorem suffix_app (X: Type) (xs ys: list X) :
suffix xs ys -> exists ws, xs = ws ++ ys.
Proof.
induction 1 as [|x xsp ysp hs [zs zeq]].
- exists []. reflexivity.
- now exists (x :: zs); rewrite zeq.
Qed.
I was trying to quickly replicate it on another machine and attempted it thus:
Theorem suffix_app (X: Type) (xs ys: list X) :
suffix xs ys -> exists ws, xs = ws ++ ys.
Proof.
induction 1.
- exists []. reflexivity.
- (* Stuck here! *)
Abort.
i.e. without the "as" clause. However, I get stuck due to the auto-named equivalent of "zeq" not being generated for reasons that I can't work out. Why isn't the (automatically named) equivalent of "zeq" generated by Coq in the second case here?
As mentioned by #ejgallego in a comment this is because the as clause allows for so-called intro-patterns (that is patterns that you can also use with the intros tactic, as mentioned by #AntonTrunov in a comment).
The [zs zeq] pattern means destruct ... as [zs zeq].
To learn more about intro-patterns, refer to https://coq.inria.fr/refman/proof-engine/tactics.html#coq:tacn.intros

Equivalence of a sequence list

Where the definition of equivalence (lequiv) in Color's library:
http://color.inria.fr/doc/CoLoR.Util.List.ListUtil.html
Require Import List.
Variable A : Type.
Definition lequiv (l1 l2: list A) : Prop := l1 [= l2 /\ l2 [= l1.
Infix "[=]" := lequiv (at level 70).
I would like to proof the lemma below. Here is my proof:
Lemma equiv_app_equiv: forall l1 l2 l3 : list A, l1 ++ l2 [=] l3 ->
l1 [=] l3 /\ l2 [=] l3.
Proof.
unfold lequiv in |- *; simpl in |- *. intuition.
apply incl_appr_incl in H0. apply H0.
A : Type
l1 : list A
l2 : list A
l3 : list A
H0 : l1 ++ l2 [=l3
H1 : l3 [=l1 ++ l2
============================
l3 [=l1
at this goal, I don't know how to go further, and I would like to know about the hypothesis H1: l3 [= l1 ++ l2 can it rewrite to : l3 [= l1 /\ l3 [= l2? I do not find any proof about this case in the Coq's library (List).
Could you please help me? do I lack something in my lemma? and is it provable? Thank you very much.
From what I could gather In is similar to ∈, [= is similar to ⊂, [=] is similar to =, and ++ is similar to ∪.
It's not true that A ∪ B = C → A = C ∧ B = C.