Coq 将假设替换为隐含,而不添加其前提作为子目标

Coq 将假设替换为隐含,而不添加其前提作为子目标,coq,Coq,这是我为使用而尝试构建的自动化的一部分。我有一个引理Is\u true\u implb\u impl:(Is\u true x->Is\u true y)Is\u true(implb x y)。我有一个形式为Is\u true(implb?x?y)的假设H,我使用Ltac elim\u Is\u true:=匹配目标…。当我在H中应用Is\u true\u impb\u impl x y时(如果我没有用x和y进行实例化,它将无法匹配),那么假设将更改为Is\u true y,我将Is\u tr

这是我为使用
而尝试构建的自动化的一部分。我有一个
引理Is\u true\u implb\u impl:(Is\u true x->Is\u true y)Is\u true(implb x y)。
我有一个形式为
Is\u true(implb?x?y)
的假设H,我使用
Ltac elim\u Is\u true:=匹配目标…
。当我在H中应用
Is\u true\u impb\u impl x y
时(如果我没有用x和y进行实例化,它将无法匹配),那么假设将更改为
Is\u true y
,我将
Is\u true x
作为一个新的子目标。(我试图通过编写一个断言
Is\u true x->Is\u true y
的策略来解决这个问题,但这也失败了,因为我无法找出如何证明断言,在断言不起作用后使用
假设
)。有什么方法可以让我把H变成
Is\u true x->Is\u true y
?在与其他
的循环中执行此操作的另一个问题是_true
消除,即表单
的新子目标是_true
匹配目标,但该策略无法对其应用任何规则

一个示例片段演示了我正在尝试做的事情:

From Coq Require Export Init.Datatypes.
From Coq Require Export Bool.Bool.

Lemma Is_true_implb_impl x y :
  (Is_true x -> Is_true y) <-> Is_true (implb x y).
Proof.
  destruct x; simpl; split; intros H.
  - apply H. apply I.
  - intros H'. assumption.
  - apply I.
  - intros H'. exfalso. assumption.
Qed.

Ltac elim_Is_true :=
  match goal with
  (* FAILS: *)
  (* | [H : Is_true (implb ?x ?y) |- _] => apply Is_true_implb_impl in H *)
  | [H : Is_true (implb ?x ?y) |- _] => apply (Is_true_implb_impl x y) in H
  | _ => idtac
  end.

Example test x y :
  Is_true x -> Is_true (implb x y) -> Is_true y.
Proof.
  intros H1 H2. elim_Is_true.
  (* In this case this is useful but in other cases I do not yet want to add
     the premise as a subgoal *)
Abort.
来自Coq的
需要导出Init.Datatypes。
从Coq需要导出Bool.Bool。
引理是真的
(Is_true x->Is_true y)Is_true(implb x y)。
证据
破坏x;单纯形;分裂介绍H。
-应用,应用。
-介绍H’。假定
-申请我。
-介绍H’。埃克斯法索。假定
Qed。
Ltac elim_是真的:=
将目标与
(*失败:)
(*|[H:Is_true(implb?x?y)|-|]=>apply Is_true_implb_impl in H*)
|[H:Is_true(implb?x?y)|-]=>在H中应用(Is_true_implb?u impl x y)
|_uz=>idtac
终止
示例测试x y:
是真x->是真(implb x y)->是真y。
证据
简介H1H2。埃利姆是真的。
(*在这种情况下,这很有用,但在其他情况下,我还不想添加
前提作为子目标*)
中止

应用
不是你想要的。引用

应用的策略试图将当前目标与术语类型的结论相匹配。如果成功,那么该策略返回的子目标数与术语类型的非依赖前提数相同

Apply将为每个(非依赖)参数生成子目标,在您的情况下,包括
Is\u true x
(除了您已有的目标:
Is\u true y

相反,你所能做的是模仿
应用
的假设替换行为,但更好地控制新假设是什么


Ltac elim_Is_true :=
  match goal with
  | H : Is_true (implb ?x ?y) |- _ =>
          (* Generate a new name for a temporary hypothesis *)
          let H' := fresh in
          (* rename the old hypothesis to this new name *)
          rename H into H';
          (* replace the goal with (Is_true x -> Is_true y) -> ?Goal *)
          generalize (proj2 (Is_true_implb_impl x y) H');
          (* intro (Is_true x -> Is_true y) with the old name *)
          intro H;
          (* Get rid of the old hypothesis *)
          clear H'
  | _ => idtac
  end.
我们使用
proj2(Is\u true\u implb\u impl x y)H'
,因为我们需要

Tactic Notation "ng_apply" constr(X) "in" constr(H) :=
  let H' := fresh in
  rename H into H';
  generalize (X H'); intro H;
  clear H'.
Ltac elim_Is_true :=
  lazymatch goal with
  | H : Is_true (implb ?x ?y) |- _ =>
          ng_apply (proj2 (Is_true_implb_impl x y)) in H
  end.
Ltac ng_apply X H :=
  first [
    let X' := fresh in let Y := fresh in let Z := fresh in
    set (X' := X);
    destruct X' as [Y Z] in X';
    first [ng_apply Y H | ng_apply Z H];
    clear Y; clear Z
  | let H' := fresh in
    rename H into H';
    generalize (X H');
    intro H;
    clear H'
  ].