如何调试比赛目标分支中的战术失败?

How to debug tactic failure in a match goal branch?

假设我在 match goal 分支的主体中有一些复杂的策略,这些策略很容易以我可能需要调试的方式出错。如果某些策略失败,是否有办法从分支获取“真实”错误消息,而不是简单地获取“错误:没有匹配目标的匹配子句”?

以这种假策略为例,其中 apply A, B, C 有几次出错的机会。我今天一直在用有点类似的真实战术战斗。

Ltac three_applications :=
    match goal with
        | [
            A : (* something reasonable *),
            B : (* something reasonable *),
            C : (* something reasonable *)
        |- _ ]  =>
            idtac A B C;
            assert (F: (* something reasonable *))
                by apply A, B, C;
            solve [discriminate F]
    end.

提前致谢!

最简单的方法是使用 lazymatch goal,但它具有不同的语义,但正如我所见,您只匹配一种形状,这对您来说可能没问题。

想法是 match goal 可能会回溯:如果你有

match goal with
| n : nat |- _ => destruct n ; reflexivity
| |- nat => exact 0
end.

它会首先尝试在你的假设中找到一些 n : nat,从最近的开始,然后尝试策略 destruct n ; reflexivity。如果失败,它将尝试找到另一个自然数。如果它们都失败了,那么它将查找目标是否与第二个子句匹配,如果匹配则执行 exact 0。 如果再次失败,它将再次回溯并得出结论 No matching clauses for match goal.

另一方面,

lazymatch goal with
| n : nat |- _ => destruct n ; reflexivity
| |- nat => exact 0
end.

会找到第一个匹配的分支,然后应用该策略,如果失败,则在lazymatch中不回溯,并给出相应分支中策略的错误。

请注意,当我找不到回溯的用例时,我总是会使用 lazymatch,而不仅仅是为了调试目的。


如果 lazymatch 在语义上不等同于您的 match 并且需要涉及回溯那么它会更难,但实际上,使用 idtac A B C 可以帮助您了解哪个在启动错误之前选择它的分支。 有时,写作

Fail three_applications.

而不仅仅是

three_applications.

会有所帮助,因为 Fail 通常会保留您在命令中进行的打印,即使它最终失败了。

了解分支后,只需手动应用您的策略即可。