我想你可能正在寻找progress
战术。如果你这样做:
Ltac my_auto_unfold := repeat match goal with
| [ H: ?P |- ?P ] => progress unfold blah in H
end.
然后它将blah
在两个假设中展开。你甚至可以这样做:
Ltac in_all_hyps tac :=
repeat match goal with
| [ H : _ |- _ ] => progress tac H
end.
概括这种模式。请注意,这可能会在每个假设中多次运行该策略。
如果您想按顺序遍历所有假设一次,这将更加困难(尤其是如果您想保留 evar 上下文而不是在证明项中添加愚蠢的东西)。这是执行此操作的快速而肮脏的方法(假设您的策略没有与目标混淆):
Parameter C: Prop.
Definition blah := C.
Definition BLOCK := True.
Ltac repeat_until_block tac :=
lazymatch goal with
| [ |- BLOCK -> _ ] => intros _
| [ |- _ ] => tac (); repeat_until_block tac
end.
Ltac on_each_hyp_once tac :=
generalize (I : BLOCK);
repeat match goal with
| [ H : _ |- _ ] => revert H
end;
repeat_until_block
ltac:(fun _
=> intro;
lazymatch goal with
| [ H : _ |- _ ] => tac H
end).
Theorem g: blah -> blah -> fst (id blah, True).
Proof.
intros.
on_each_hyp_once ltac:(fun H => unfold blah in H).
这个想法是您插入一个虚拟标识符来标记您在目标中的位置(即,标记可以引入多少变量),然后将所有上下文还原为目标,以便您可以重新引入上下文之一一次假设,对您刚刚介绍的每个假设运行策略。