Coq 仅折叠应用程序

Coq 仅折叠应用程序,coq,coq-tactic,Coq,Coq Tactic,fold策略用另一个术语替换所有出现的术语,因此fold(id f)尝试用(id f)替换所有出现的f 但是,我只想在出现在上下文(f[])中时折叠f,而不是在上下文([]f)中折叠。尤其是重复myfold(id f),不应循环 有没有一个一般的方法来做这种类型的折叠?我现在最好的就是 repeat match goal with | |- context [(f ?x)] => change (f x) with ((id f) x) end 但上述内容不适用于形式为的上下文,对于所有

fold
策略用另一个术语替换所有出现的术语,因此
fold(id f)
尝试用
(id f)
替换所有出现的
f

但是,我只想在出现在上下文
(f[])
中时折叠
f
,而不是在上下文
([]f)
中折叠。尤其是
重复myfold(id f)
,不应循环

有没有一个一般的方法来做这种类型的折叠?我现在最好的就是

repeat match goal with
| |- context [(f ?x)] => change (f x) with ((id f) x)
end

但上述内容不适用于形式为
的上下文,对于所有x,fx=fx

您可以使用不包含
f
的中间值。差不多

let f' := fresh in
pose (id f) as f';
change f with f'
change (id f') with f'; (* undo the change in locations where we've already added id *)
subst f'.
编辑

如果您确实想在应用程序上下文中折叠东西,可以使用三个中间值,如下所示:

(* Copyright 2018 Google LLC.
   SPDX-License-Identifier: Apache-2.0 *)
Ltac myfold_id f :=
  let id_f := fresh in
  let id_f_good := fresh in
  let f' := fresh in
  pose (id f) as id_f;
  pose (id f) as id_f_good;
  pose f as f';
  repeat (change f with id_f at 1;
          lazymatch goal with
          | [ |- context[id_f _] ] => change id_f with id_f_good
          | _ => change id_f with f'
          end);
  subst id_f id_f_good f'.
Goal let f := id in (f = f, f 0) = (f = f, f 0).
Proof.
  intro f.
  (* (f = f, f 0) = (f = f, f 0) *)
  myfold_id f.
  (* (f = f, id f 0) = (f = f, id f 0) *)

这可以防止循环,但仍会将
(gf)
更改为
(gf)(gf))
更新为不将
gf
更改为
gf(df)