Coq将功能扩展为目标的一部分是什么意思?

时间:2019-01-23 22:09:19

标签: coq

我试图解决以下定理,并陷入最后一个def validation(): ... def main(): ... if __name__ == '__main__': validation() main()

simpl.

这时Coq将目标从以下位置更改:

Lemma nonzeros_app : forall l1 l2 : natlist,
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).
Proof.
  intros l1 l2. induction l1 as [| n' l' IHl'].
  -simpl. reflexivity.
  -simpl. 
Qed.

收件人:

1 subgoal (ID 170)

  n' : nat
  l', l2 : natlist
  IHl' : nonzeros (l' ++ l2) = nonzeros l' ++ nonzeros l2
  ============================
  nonzeros ((n' :: l') ++ l2) = nonzeros (n' :: l') ++ nonzeros l2

在我看来,这完全是个谜。 Coq只是复制将函数的定义粘贴到我的目标中是什么意思?我什至该怎么办?


问题背景:

有人告诉我解决方法是:

1 subgoal (ID 185)

  n' : nat
  l', l2 : natlist
  IHl' : nonzeros (l' ++ l2) = nonzeros l' ++ nonzeros l2
  ============================
  match n' with
  | 0 => nonzeros (l' ++ l2)
  | S _ => n' :: nonzeros (l' ++ l2)
  end =
  match n' with
  | 0 => nonzeros l'
  | S _ => n' :: nonzeros l'
  end ++ nonzeros l2

这让我想了解为什么他们在Lemma nonzeros_app : forall l1 l2 : natlist, nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2). Proof. intros l1 l2. induction l1. - simpl. reflexivity. - simpl. { induction n. - ... - ... } Qed. 上使用归纳法,因为我觉得在那里永远不会使用归纳法。所以我问,为什么?但是我意识到,在问起我为什么之前甚至不了解证明状态之前,我就意识到了,因为这似乎只是将粘贴复制到了证明状态(这对我来说没有意义)。因此,在我问为什么要使用归纳法之前,我必须先问一下证明状态是什么,也许这可以弄清楚为什么对n进行归纳法。

1 个答案:

答案 0 :(得分:1)

我假设您已经通过以下方式(或类似方式)定义了nonzeros

Require Import List.
Import ListNotations.


Definition natlist := list nat.

Fixpoint nonzeros (l : natlist) :=
  match l with
  | [] => []
  | 0 :: xs => nonzeros xs
  | x :: xs => x :: nonzeros xs
  end.

因此nonzeros是递归的,而l的结构递减。 Coq的simpl策略采用一种启发式方法,在该方法中,如果将固定点的定义应用于以构造函数为开头符号的术语,则会展开该定义。 在您的情况下,例如nonzeros (n' :: l'),常量nonzeros后跟由构造函数Cons(= {::)组成的术语。 Coq执行所谓的“减少增量”,用其定义替换nonzero的出现。由于该定义是match,因此您将获得match作为新术语。进一步的替换确实可以简化它,但是不能消除两种情况:一种表示零水头,一种表示非零水头。

发生nonzeros ((n' :: l') ++ l2)时也会发生同样的情况,该事件首先简化为nonzeros (n' :: (l' ++ l2)),因此自变量的开头也是Cons

如果要避免在简化时公开match表达式,可以在nonzeros的定义后加上以下指令:

Arguments nonzeros l : simpl nomatch.

这特别告诉simpl避免扩展术语,以免最终在更改位置暴露match

关于您的朋友在这里使用的induction:用于强制将案例拆分为n',以便每个案例(n' = 0n' = S _)都可以分开处理。实际上,这里不需要归纳法。一个简单的大小写拆分(case n')可以做到这一点。