如何将 do 策略应用于序列

How to apply do tactic to a sequence

深入研究 test_nostutter_1 excersize 我找到了一种无需重复即可解决该问题的方法:

Example test_nostutter_1: nostutter [3;1;4;1;5;6].
Proof.
  constructor 3.
  (* This will apply the tactics to the 2-nd subgoal *)
  2: {apply eqb_neq. auto. }
  constructor 3.
  2: {apply eqb_neq. auto. }
  constructor 3.
  2: {apply eqb_neq. auto. }
  constructor 3.
  2: {apply eqb_neq. auto. }
  constructor 2.
Qed.

我决定更多地使用它,在 coq 参考手册中我发现 do tactical 可以多次循环一个策略。

do num expr

expr is evaluated to v which must be a tactic value. This tactic value v is applied num times. Supposing num > 1, after the first application of v, v is applied, at least once, to the generated subgoals and so on. It fails if the application of v fails before the num applications have been completed.

所以我尝试了这个:

do 4 constructor 3; 2: {apply eqb_neq. auto. }

可惜失败了。只有这个有效:

do 1 constructor 3.

是否可以使用 do 使其工作?

回答

行中有几个问题

do 4 constructor 3; 2: {apply eqb_neq. auto. }

首先,不能在链运算符;后面使用2:{}。您可以使用的最接近的是 sequence with local application tac; [tac1 | tac2]。由于我们只想在第二个分支上做一些事情,我们可以在这里省略 tac1

此外,您不能在战术中使用句点。句点标记语句的结尾,但整个 do 表达式是单个语句。您应该始终使用序列运算符 ; 来链接多个策略。

最后,do n tac; tac 的工作方式类似于 (do n tac); tac。您可以用括号将策略表达式括起来,例如do n (tac; tac) 改变行为。

所以这个应该可以工作:

do 4 (constructor 3; [ | apply eqb_neq; auto ]).

题外话

我们可以通过多种方式简化线路。

  • auto 可以给出额外的定理来自动化。任何可以用 apply eqb_neq; auto 解决的目标也可以用 auto using eqb_neq.
  • 解决
do 4 (constructor 3; [ | auto using eqb_neq ]).
  • auto 策略永远不会失败,因此它可以安全地用于两个分支。
do 4 (constructor 3; auto using eqb_neq).
  • repeat 重复直到出现问题或没有更多的子目标。以下将重复,直到第三个构造函数不再适用。
repeat (constructor 3; auto using eqb_neq).
  • 我们可以让 Coq 选择应用哪个构造函数。这样就可以完成(或接近完成)证明了。
repeat (constructor; auto using eqb_neq).
  • 我们还可以通过 auto 使用 Hint Constructors 命令使 nostutter 的构造函数自动化。现在我们可以 auto 整件事了。 (您可以将提示命令放在 nostutter 的定义之后,然后您就可以 auto 它无处不在。)
Hint Constructors nostutter.
auto using eqb_neq.
(* if the above fails, the following increases the search depth so it should succeed. *)
auto 6 using eqb_neq.
  • 实际上,定理 eqb_neq 已经为 auto 注册了。所以我们可以:
auto 6.