如何在ltac中调用rewrite
只重写一次?我认为coq的文档提到了rewrite at
的一些内容,但我在实践中并没有真正使用它,也没有例子。
这是我想要做的一个例子:
Definition f (a b: nat): nat.
Admitted.
Theorem theorem1: forall a b: nat, f a b = 4.
Admitted.
Theorem theorem2: forall (a b: nat), (f a b) + (f a b) = 8.
Proof.
intros a b.
(*
my goal here is f a b + f a b = 8
I want to only rewrite the first f a b
The following tactic call doesn't work
*)
rewrite -> theorem1 at 1.
答案 0 :(得分:4)
当我按照你的建议尝试rewrite -> theorem1 at 1.
时,我会得到
以下错误消息:
Error: Tactic failure: Setoid library not loaded.
因此,作为反应,我重新启动了您的脚本,包括以下命令 在一开始。
Require Import Setoid.
现在,它可以工作(我正在使用coq 8.6进行测试)。
答案 1 :(得分:2)
您正在使用策略的rewrite at
变体,因为手册指定的变体总是通过setoid重写来执行(请参阅https://coq.inria.fr/refman/Reference-Manual010.html#hevea_tactic121)。
更好地控制重写规则的另一种可能性是断言所需重写的一般形状(这里将通过theorem1
证明),然后使用新假设执行重点重写。
无需借助任何图书馆即可使用:
intros a b.
assert (H: f a b + f a b = 4 + f a b) by (rewrite theorem1; reflexivity).
rewrite H.
答案 2 :(得分:2)
有几种选择,其中一种是由@Yves指出的。
另一个选择是使用pattern
策略:
pattern (f a b) at 1.
rewrite theorem1.
这里的诀窍实际上是pattern (f a b) at 1.
改变了目标
f a b + f a b = 8
到
(fun n : nat => n + f a b = 8) (f a b)
基本上,它会扩展您的目标,在第一次出现f a b
时进行抽象。此外,通常rewrite
不会在绑定器(例如lambdas)下重写,因为如果确实如此,您可以从let {#1}}转到{{{} 1}},在香草Coq中不相等。
然后fun x => x + 0
将参数fun x => x
重写为rewrite theorem1.
并简化一点(它会进行beta减少),因此您获得(f a b)
。
旁注:你也可以使用4
这样的策略:
4 + f a b = 8