Potykam się o zachowanie sprawdzania terminatora Coq, którego sam nie potrafię wyjaśnić. Rozważmy:Kiedy narzędzie do sprawdzania zakończenia redukuje dostęp do rekordu
Require Import Coq.Lists.List.
Record C a := { P : a -> bool }.
Arguments P {_}.
Definition list_P {a} (a_C : C a) : list a -> bool := existsb (P a_C).
Definition list_C {a} (a_C : C a) : C (list a) := {| P := list_P a_C |}.
(* Note that *)
Eval cbn in fun a C => (P (list_C C)).
(* evaluates to: fun a C => list_P C *)
Inductive tree a := Node : a -> list (tree a) -> tree a.
(* Works, using a local record *)
Fixpoint tree_P1 {a} (a_C : C a) (t : tree a) : bool :=
let tree_C := Build_C _ (tree_P1 a_C) in
let list_C' := Build_C _ (list_P tree_C) in
match t with Node _ x ts => orb (P a_C x) (P list_C' ts) end.
(* Works too, using list_P directly *)
Fixpoint tree_P2 {a} (a_C : C a) (t : tree a) : bool :=
let tree_C := Build_C _ (tree_P2 a_C) in
match t with Node _ x ts => orb (P a_C x) (list_P tree_C ts) end.
(* Does not work, using a globally defined record. Why not? *)
Fixpoint tree_P3 {a} (a_C : C a) (t : tree a) : bool :=
let tree_C := Build_C _ (tree_P3 a_C) in
match t with Node _ x ts => orb (P a_C x) (P (list_C tree_C) ts) end.
Pierwszy i Drugi przykład pokazuje, że gdy próbuje zrozumieć czy fixpoint jest zakończenie, Coq jest w stanie rozwiązać rekordowe akcesorów, w zasadzie oceny co pisaliśmy w tree_P1
co pisaliśmy w tree_P2
.
Ale wydaje się, że działa tylko wtedy, gdy rekord jest zbudowany lokalnie (let tree_C :=…
), a nie, jeśli jest zdefiniowany przy użyciu Definition
.
Ale Fixpoint
może dokładnie przejrzeć inne definicje, np. przez list_P
. Co jest specjalnego w nagraniach i czy mogę sprawić, aby Coq zaakceptował tree_P3
?