在Coq中写Ltac
时,可能会想写
try match goal with
|- context [?x && true] => rewrite andb_true_r
end
而不是
try rewrite andb_true_r
不要毫无意义地调用rewrite
- 这在一个更大的策略的内部循环中,我们希望在大多数情况下重写失败。
但这实际上更快吗?或者rewrite
失败的速度和我写的手写match
一样快吗?
答案 0 :(得分:4)
在您自我回答的基础上,Coq对所使用的精确匹配策略很敏感。请注意以下策略之间的区别:
rewrite
我怀疑match
使用的匹配策略类似于我用constr_eq
写的orb ?a ?b
;它查找rewrite
的出现次数,然后尝试从左到右实例化evars并根据需要进行语法相等性检查。显然,这会产生很大的成本。我打开了an issue on Coq's bug tracker。
然而,这个成本可能是不可避免的,因为match
匹配模β,与Goal forall b, b || (fun x => x) true = true.
intros.
Fail match goal with |- context [_ || true] => rewrite orb_true_r end.
rewrite orb_true_r. (* succeeds *)
不同。考虑:
setoid_rewrite
在Map
中加速更加明显,在许多情况下它会重写模数展开,因此可以不必要地减少你的目标,一遍又一遍地失败。
答案 1 :(得分:2)
是的,它是!在我的一个策略中,我实现了60%的加速。
以下是显示此行为的另一个微基准:
Require Import Coq.Bool.Bool.
Goal forall b, b = true.
intros.
(* Lets create a large goal *)
do 300 rewrite <- orb_false_r with (b := b).
Time do 300 try rewrite orb_true_r.
(* Finished transaction in 2.57 secs (2.431u,0.003s) (successful) *)
Time do 300 try lazymatch goal with |- context [_ || true] => rewrite orb_true_r end.
(* Finished transaction in 0.05 secs (0.05u,0.s) (successful) *)
Abort.