Coq:出现在箭头左侧时,目标变量未通过归纳转换

Coq:出现在箭头左侧时,目标变量未通过归纳转换,coq,induction,Coq,Induction,我试图用l上的归纳法证明下面的定理。这在纸上是一个简单的定理,但是当我试图用Coq证明它时,我并没有达到我期望的归纳目标 Theorem nodup_app__disjoint: forall {X: Type} (l: list X), (forall l1 l2 : list X, l = l1 ++ l2 -> Disjoint l1 l2) -> NoDup l. Proof. intros X l. induction l. - intros F. apply

我试图用l上的归纳法证明下面的定理。这在纸上是一个简单的定理,但是当我试图用Coq证明它时,我并没有达到我期望的归纳目标

Theorem nodup_app__disjoint: forall {X: Type} (l: list X),
  (forall l1 l2 : list X, l = l1 ++ l2 -> Disjoint l1 l2) -> NoDup l.
Proof.
  intros X l. induction l.
  - intros F. apply nodup_nil.
  - (* ??? *)
此时的国家:

1 subgoal
X : Type
x : X
l : list X
IHl : (forall l1 l2 : list X, l = l1 ++ l2 -> Disjoint l1 l2) -> NoDup l
______________________________________(1/1)
(forall l1 l2 : list X, x :: l = l1 ++ l2 -> Disjoint l1 l2) ->
NoDup (x :: l)
但这根本不是我所期望的目标!难道不应该用
l=l1++l2
代替
x::l=l1++l2

以下是我正在处理的命题,以防您想重现问题并亲自查看:

Inductive Disjoint {X : Type}: list X -> list X -> Prop :=
  | disjoint_nil: Disjoint [] []
  | disjoint_left: forall x l1 l2, Disjoint l1 l2 -> ~(In x l2) -> Disjoint (x :: l1) l2
  | disjoint_right: forall x l1 l2, Disjoint l1 l2 -> ~(In x l1) -> Disjoint l1 (x :: l2).

Inductive NoDup {X: Type}: list X -> Prop :=
  | nodup_nil: NoDup []
  | nodup_cons: forall hd tl, NoDup tl -> ~(In hd tl) -> NoDup (hd :: tl).
但这根本不是我所期望的目标!难道不应该用
l=l1++l2
代替
x::l=l1++l2

简短回答:不应该

列表的归纳原则 让我们回顾一下列表的归纳原则:

Check list_ind.
(*
list_ind
  : forall (A : Type) (P : list A -> Prop),
    P [] ->
    (forall (a : A) (l : list A), P l -> P (a :: l)) ->
    forall l : list A, P l
*)
这意味着为了证明谓词
p
适用于所有列表(
forall l:list a,pl
),需要证明

  • P
    保留空列表--
    P[]
  • P
    适用于所有非空列表,因为它适用于它们的尾部--
    (对于所有(a:a)(l:list a),pl->P(a::l))
将列表归纳原则应用于目标 现在,我们有以下目标:

(forall l1 l2, l = l1 ++ l2 -> Disjoint l1 l2) -> NoDup l.
为了了解当我们试图通过归纳法证明
l
的陈述时应该达到什么目标,让我们机械地将上面的
l
替换为
[]
,另一种替换为
h::tl

[]
案例:

(forall l1 l2, [] = l1 ++ l2 -> Disjoint l1 l2) -> NoDup [].
(forall l1 l2, h :: tl = l1 ++ l2 -> Disjoint l1 l2) -> NoDup (h :: tl).
h::tl
案例:

(forall l1 l2, [] = l1 ++ l2 -> Disjoint l1 l2) -> NoDup [].
(forall l1 l2, h :: tl = l1 ++ l2 -> Disjoint l1 l2) -> NoDup (h :: tl).
这是您在上面得到的(以重命名为模)。对于第二种情况,你也得到了归纳假设,我们从原始语句中用
tl
代替
l

(forall l1 l2, tl = l1 ++ l2 -> Disjoint l1 l2) -> NoDup tl.

顺便说一句,该定理是可证明的,您可能会发现以下辅助引理很有用:

Lemma disjoint_cons_l {X} (h : X) l1 l2 :
  Disjoint (h :: l1) l2 -> Disjoint l1 l2.
Admitted.

Lemma disjoint_singleton {X} h (l : list X) :
  Disjoint [h] l -> ~ In h l.
Admitted.

我不确定我是否理解你的定理。
中的
l
对于所有l1-l2,l=l1++l2->不相交的l1-l2
似乎没有用。在我看来,归纳方案似乎还可以:由
l
绑定的每个实例都将被
nil
x::l
替换。你能说出你想证明的引理吗?也许你用Coq翻译的不正确?另外,你的引理中可能缺少
NoDup l1
NoDup l2
?只是胡乱猜测;)@Vinz前提是,对于列表
l
的任何“切块”,“部分”(
l1
l2
)是不相交的。这意味着
l
没有重复项。如果在
l
中有重复项,它的形式将是
l'+[x]++l'+[x]++l'
,这将使我们产生矛盾,因为
l1
=
l'+[x]
l2
=
l'+[x]++l'
是不相交的。。好吧,我弄错了。谢谢我想你设法把问题的困难归结为这两个引理,因为我对这两个引理都完全不了解!我需要什么特别的技巧吗?对各种参数的归纳使我一无所获。注意,我重用了标准的
NoDup
谓词。您可能需要使用
记住
策略。