在包含局部变量的调用上与 Ltac 匹配

Matching with Ltac on a call containing local variable

我有一个目标,其中包含对匹配分支内的某个引理 foo 的调用。该调用使用分支本地变量 R 作为其参数之一:

| SomeConstr => fun R => .... (foo a b c R) ....

我想在 foo 上执行 beta 扩展,以便调用变为:

| SomeConstr => fun R => .... ((fun d => foo a b c d) R) ....

这将使我能够进一步概括 (fun d => foo a b c d),这将不再依赖分支的本地变量。因为我正在处理非常大的证据,所以我想用 Ltac 来写这个。这是一个尝试:

match goal with
| [ |- context[(foo ?A ?B ?C ?R)] ] =>
  let d := fresh "d" in
  replace (foo A B C R) with ((fun d => foo A B C d) R)
end.

但是 "No matching clause for match" 失败了。如果我用 idtac 替换 match 分支的主体,它仍然会失败,所以问题显然是由于未能匹配给定表达式引起的。但是,如果我少匹配一个参数,则匹配成功。例如:

match goal with
| [ |- context[(foo ?A ?B ?C)] ] =>
  idtac A; idtac B; idtac C
end.

在连续的行中打印 "a"、"b" 和 "c"。我也可以说:

match goal with
| [ |- context[(foo ?A ?B ?C)] ] =>
  let d := fresh "d" in
  replace (foo A B C) with (fun d => foo A B C d) by auto
end.

这成功了,但有趣的是目标保持不变,即。调用的形式仍然是 (foo a b c R) 而不是 ((fun d => foo a b c d) R)。我在这里做错了什么?

replace 策略执行 β 减少。你可以通过写

看到这个
Goal True.
  replace True with ((fun x => x) True) by auto.

如果您改为使用 change 策略(仅当 replace 的附带条件可以通过 reflexivity 解决时才有效),那么它应该有效。例如,

Goal True.
  change True with ((fun x => x) True).

将目标更改为 (fun x : Prop => x) True

这没有记录,我已将其报告为 an issue on GitHub