我如何编写像"破坏......一样"的策略?

phs*_*phs 6 coq ltac

在coq中,该destruct策略有一个变体接受"连接析取引入模式",允许用户为引入的变量分配名称,即使在解包复杂的归纳类型时也是如此.

coq中的Ltac语言允许用户编写自定义策略.我想写(实际上,维持)一种策略,在将控制权交给之前做一些事情destruct.

我希望我的自定义策略允许(或要求,更容易)用户提供我的策略可以提供的介绍模式destruct.

Ltac语法实现了什么?

Art*_*rim 6

您可以使用参考手册中描述的策略符号.例如,

Tactic Notation "foo" simple_intropattern(bar) :=
  match goal with
  | H : ?A /\ ?B |- _ =>
    destruct H as bar
  end.

Goal True /\ True /\ True -> True.
intros. foo (HA & HB & HC).
Run Code Online (Sandbox Code Playgroud)

simple_intropattern指令指示Coq解释bar为一个介绍模式.因此,调用foo导致调用destruct H as (HA & HB & HC).

这是一个更长的例子,展示了更复杂的引入模式.

Tactic Notation "my_destruct" hyp(H) "as" simple_intropattern(pattern) :=
  destruct H as pattern.

Inductive wondrous : nat -> Prop :=
  | one         : wondrous 1
  | half        : forall n k : nat,         n = 2 * k -> wondrous k -> wondrous n
  | triple_one  : forall n k : nat, 3 * n + 1 = k     -> wondrous k -> wondrous n.

Lemma oneness : forall n : nat, n = 0 \/ wondrous n.
Proof.
  intro n.
  induction n as [ | n IH_n ].

  (* n = 0 *)
  left. reflexivity.

  (* n <> 0 *)
  right. my_destruct IH_n as
    [ H_n_zero
    | [
      | n' k H_half       H_wondrous_k
      | n' k H_triple_one H_wondrous_k ] ].

Admitted.
Run Code Online (Sandbox Code Playgroud)

我们可以检查其中一个生成的目标,以查看名称的使用方式.

oneness < Show 4.
subgoal 4 is:

  n : nat
  n' : nat
  k : nat
  H_triple_one : 3 * n' + 1 = k
  H_wondrous_k : wondrous k
  ============================
   wondrous (S n')
Run Code Online (Sandbox Code Playgroud)