考虑下面的代码:为什么构造函数在这里花了很长时间?
Inductive Even : nat -> Prop :=
| EO : Even O
| ESS : forall n, Even n -> Even (S (S n)).
Fixpoint is_even_prop (n : nat) : Prop :=
match n with
| O => True
| S O => False
| S (S n) => is_even_prop n
end.
Theorem is_even_prop_correct : forall n, is_even_prop n -> Even n.
Admitted.
Example Even_5000 : Even 5000.
Proof.
apply is_even_prop_correct.
Time constructor. (* ~0.45 secs *)
Undo.
Time (constructor 1). (* ~0.25 secs *)
Undo.
(* The documentation for constructor says that "constructor 1"
should be the same thing as doing this: *)
Time (apply I). (* ~0 secs *)
Undo.
(* Apparently, if there's only one applicable constructor,
reflexivity falls back on constructor and consequently
takes as much time as that tactic: *)
Time reflexivity. (* Around ~0.45 secs also *)
Undo.
(* If we manually reduce before calling constructor things are
faster, if we use the right reduction strategy: *)
Time (cbv; constructor). (* ~0 secs *)
Undo.
Time (cbn; constructor). (* ~0.5 secs *)
Qed.
Theorem is_even_prop_correct_fast : forall n, is_even_prop n = True -> Even n.
Admitted.
Example Even_5000_fast : Even 5000.
Proof.
apply is_even_prop_correct_fast.
(* Everything here is essentially 0 secs: *)
Time constructor.
Undo.
Time reflexivity.
Undo.
Time (apply eq_refl). Qed.
我只是想看看,如果你能在Prop
而非Set
做反思和偶然发现了这一点。我的问题不是如何正确地进行反思,我只是想知道为什么constructor
在第一种情况下比第二种情况慢。 (也许有一些与constructor
做马上就可以看到(没有任何减少),构造函数必须在第二种情况下eq_refl
?但它仍然必须降低之后...)
此外,虽然试图找出constructor
在做什么我注意到文档没有说明策略将使用哪种减少策略。这种疏忽是否是故意的,并且这个想法是,如果你特别想要一种减少策略,你应该明确地说出你想要的减少策略(否则实施可以自由选择)?
澄清我的'构造器'的减少策略评论:我不是说减少策略必须添加到文档/规范;相反,我想知道是否有人说(在手册中)关于一般使用的策略。可能会出现这样的情况:手册中的某个地方会说“如果没有另外说明,cbv将在任何地方使用”,“您不能依赖任何正在使用的特定降低策略,而是使用哪种策略取决于实施细节并根据具体情况决定(有时是动态的)“,或类似的东西。 – cic
...因为有时这些信息似乎有用(例如,这里),但同时过度依赖这些低级细节可能会导致非常脆弱的证明脚本。 – cic