我想以交互方式构造一个存在变量。我无法使用Grab Existential Variables,因为在完成目标之前,我需要填写存在的内容。
最小的珍贵 这是一个最小的示例(因为它很简单,它具有其他解决方案,但它说明了我的问题)
Context (A:Type).
Parameter P Q: A -> Prop.
Definition filter: forall {a}, P a -> A:= fun a Pa=> a.
Lemma my_lemma:
forall a b, Q b -> (Q b -> P a) ->
exists a (H: P a), P (filter H).
Proof.
intros ?? H H0.
do 2 eexists.
这时,有两种解决方案无法回答我的问题:(1)我可以先运行(eauto
)然后再进行Grab Existential Variables
,但假设eauto直到我实例化统一变量; (2)我可以只使用instantiate(1:= H0 H)
(甚至是instantiate(1:= ltac:(eauto))
)明确地通过证明项,但假设存在证明的证明是乏味的,我们希望以交互方式进行。
我们还能做什么?我们可以尝试使用cut
或assert
,如下所示:
match goal with
|[|- P (filter ?x)] =>
match type of x with
| ?T => assert (HH:T) by eauto
end
end.
但是HH不在统一变量的上下文中,因此无法实例化。
instantiate(1:=HH). (* Instance is not well-typed in the environment of ?H. *)
据我所知,解决此问题的唯一方法是使用Show Existentials
,查看变量的类型,手动复制它,将证明回滚到引入统一之前并构造变量那里。在示例中,它看起来像这样:
Lemma my_lemma:
forall a b, Q b -> (Q b -> P a) ->
exists a (H: P a), P (filter H).
Proof.
intros ?? H H0.
do 2 eexists.
Show Existentials.
Restart. (* This command restores the proof editing process to the original goal. *)
intros ?? H H0.
assert (HH:P a) by eauto.
eexists; exists HH.
auto.
Qed.
很显然,我想避免此工作流程。那么,无论如何将存在变量变成子目标?
答案 0 :(得分:1)
您最好的选择也许是避免首先将生存变量创建为evar。您无需手动构造变量即可;如果您可以确定它的创建位置,则可以使用unshelve t
来包装令人反感的策略,从而将t
创建的所有evar都转化为目标。可能很难做到的地方是,如果相关策略深入到某种自动化中并且难以识别或更改。