Coq 如何对序列应用do策略

Coq 如何对序列应用do策略,coq,logical-foundations,Coq,Logical Foundations,深入到test\u nostutter\u 1exercise中,我找到了一种不用重复就能解决问题的方法: 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

深入到
test\u nostutter\u 1
exercise中,我找到了一种不用重复就能解决问题的方法:

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 num expr
expr被计算为v,它必须是一个策略值。此策略值v应用了num次。假设num>1,在第一个 v的应用,v至少应用一次到生成的 子目标等等。如果v的应用程序在 num应用程序已完成

所以我试了一下:

do 4 constructor 3; 2: {apply eqb_neq. auto. }
但不幸的是,它失败了。只有这样才能起作用:

do 1 constructor 3.
是否可以使用do使其工作?

回答 有几个问题

do 4 constructor 3; 2: {apply eqb_neq. auto. }
首先,不能在链式操作符
之后使用
2:
{}
。你能使用的最接近的东西是
tac;[tac1 | tac2]
。因为我们只想在第二个分支上做一些事情,所以可以在这里省略
tac1

另外,你不能在战术时间内使用句点。句点标记语句的结束,但整个
do
表达式是一条语句。您应该始终使用序列运算符
以链接多种战术

最后,
dontac;tac
的工作原理类似于
(don n tac);tac
。您可以用括号括起策略表达式,例如
don(tac;tac)
来更改行为

所以这一个应该有效:

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

离题 我们可以用几种方法简化这条线

  • auto
    可以提供额外的定理来实现自动化。任何可通过
    应用eqb_neq解决的目标;自动
    也可通过使用eqb_neq
自动解决
  • auto
    策略永远不会失败,因此它可以安全地在两个分支上使用
  • 重复
    重复,直到出现故障或不再有子目标。重复以下步骤,直到第三个构造函数不再适用
  • 我们可以让Coq选择应用哪个构造函数。这可以完成(或几乎完成)证明
  • 我们还可以通过
    auto
    使用
    Hint构造函数
    命令,使
    nostutter
    的构造函数自动化。现在我们可以
    auto
    整件事了。(您可以将提示命令放在
    nostutter
    的定义之后,然后可以
    auto
    将其放在任何地方。)
  • 实际上,定理
    eqb_neq
    已经注册为
    auto
    。所以我们可以:
答复 有几个问题

do 4 constructor 3; 2: {apply eqb_neq. auto. }
首先,不能在链式操作符
之后使用
2:
{}
。你能使用的最接近的东西是
tac;[tac1 | tac2]
。因为我们只想在第二个分支上做一些事情,所以可以在这里省略
tac1

另外,你不能在战术时间内使用句点。句点标记语句的结束,但整个
do
表达式是一条语句。您应该始终使用序列运算符
以链接多种战术

最后,
dontac;tac
的工作原理类似于
(don n tac);tac
。您可以用括号括起策略表达式,例如
don(tac;tac)
来更改行为

所以这一个应该有效:

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

离题 我们可以用几种方法简化这条线

  • auto
    可以提供额外的定理来实现自动化。任何可通过
    应用eqb_neq解决的目标;自动
    也可通过使用eqb_neq
自动解决
  • auto
    策略永远不会失败,因此它可以安全地在两个分支上使用
  • 重复
    重复,直到出现故障或不再有子目标。重复以下步骤,直到第三个构造函数不再适用
  • 我们可以让Coq选择应用哪个构造函数。这可以完成(或几乎完成)证明
  • 我们还可以通过
    auto
    使用
    Hint构造函数
    命令,使
    nostutter
    的构造函数自动化。现在我们可以
    auto
    整件事了。(您可以将提示命令放在
    nostutter
    的定义之后,然后可以
    auto
    将其放在任何地方。)
  • 实际上,定理
    eqb_neq
    已经注册为
    auto
    。所以我们可以:

该定理由本书的作者用以下方法证明:
重复构造函数;应用eqb_neq;自动。
我刚决定寻找替代方法,使用不同的战术和参数,这对教育非常有用。如果我尝试“构造函数,你能告诉我吗。[>|应用eqb_neq]”。在定理开始时,它失败了,并显示消息:“错误:目标数不正确(预期1个战术,给出2个)。”。为什么会发生这种情况?我希望它将eqb_neq应用于第二个子目标。@user4035这是因为默认情况下该策略仅应用于第一个子目标。我想你可以
all:[>|…])。
尽管它不是很有用。这本书的作者用以下方法证明了这个定理:
重复构造函数;应用eqb_neq;自动。
我刚决定寻找替代方法,使用不同的战术和参数,这对教育非常有用。如果我尝试“构造函数,你能告诉我吗。[>|应用eqb_neq]”。在定理开始时,它失败了,并显示消息:“错误:目标数不正确(预期1个战术,给出2个)。”。为什么会发生这种情况?我希望它将eqb_neq应用于第二个子目标。@user4035这是因为默认情况下该策略仅应用于第一个子目标。我想你可以
all:[>|…]。
尽管它不是很有用。
repeat (constructor 3; auto using eqb_neq).
repeat (constructor; auto using eqb_neq).
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.
auto 6.