Coq中的可扩展策略

时间:2018-02-19 14:21:30

标签: coq ltac

让我说我有一种奇特的策略可以解决某种类型的引理:

Ltac solveFancy :=
  some_preparation;
  repeat (first [important_step1 | important_step2];
          some_cleanup);
  solve_basecase.

现在我用这种策略来证明那种类型的引理,我后来想用这种术语。

Lemma fancy3 := …. Proof. … Qed.
Ltac important_step3 := apply fancy3;[some|specific|stuff].

现在我可以简单地重新定义Ltac solveFancy ::= …并将important_step3添加到列表中,但很快就会变老。

现在有更优雅的方法来扩展important_step中的solveFancy - 战术列表吗?我想象的是:

Add Hint SolveFancy important_step3.

2 个答案:

答案 0 :(得分:1)

这不是我所说的优雅,但这是一个纯粹的Ltac解决方案。您可以在后面重新定义的策略中留下一个钩子,并且可以通过始终为下一个提示留下钩子来继续遵循此模式:

Axiom P : nat -> Prop.
Axiom P0 : P 0.
Axiom P_ind : forall n, P n -> P (S n).

Ltac P_hook := fail.

Ltac solve_P :=
  try apply P_ind;
  exact P0 || P_hook.

Theorem ex_1 : P 1.
Proof.
  solve_P.
Qed.

Ltac P_hook2 := fail.
Ltac P_hook ::= exact ex_1 || P_hook2.

Theorem ex_2 : P 2.
Proof.
  solve_P.
Qed.

Ltac P_hook3 := fail.
Ltac P_hook ::= exact ex_2 || P_hook3.

Theorem ex_3 : P 3.
Proof.
  solve_P.
Qed.

应该有一种方法可以使用Hint Extern执行此操作,但是它会更难以控制这些提示的尝试时间和顺序,并且它们必须在最后完全解决目标

答案 1 :(得分:0)

我会在solveFancy上添加一个参数,您可以使用该参数来传递另一种策略:

Ltac solveFancy hook :=
  some_preparation;
  repeat (first [important_step1 | important_step2 | hook];
          some_cleanup);
  solve_basecase.

(* use solveFancy without any extra available steps *)
[...] solveFancy fail [...]

Ltac important_step3 := [...]

(* use solveFancy with important_step3 *)
[...] solveFancy important_step3 [...]

尽管它不能单独解决可扩展性问题,但它比重新定义钩子更为优雅。以下是利用模块允许在不覆盖先前定义的情况下重新定义Ltac名称这一事实,根据其本身的先前版本反复重新定义策略x的策略。

Ltac x := idtac "a".

Goal False.
  x. (* a *)
Abort.

Module K0.
  Ltac x' := x.
  Ltac x := x'; idtac "b".
End K0.
Import K0.

Goal False.
  x. (* a b *)
Abort.

Module K1.
  Ltac x' := x.
  Ltac x := x'; idtac "c".
End K1.
Import K1.

Goal False.
  x. (* a b c *)
Abort.

请注意,模块的名称K0K1并不重要,可以根据需要对它们进行重命名或重新排序。这不是世界上最优雅的事情,但我认为这是一种进步。