Ich stolpere über Verhalten von Coqs Termination Checker, die ich mir nicht erklären kann. Bedenken Sie:Wann reduziert die Terminierungsprüfung einen Datensatz Accessor
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.
Die erste und zweite Beispiel zeigt, dass, wenn sie versuchen, zu verstehen, ob ein Fixpunkt ist beendet, Coq der Lage ist, Rekord Accessoren zu lösen, im Grunde die Bewertung, was wir in tree_P1
zu geschrieben, was wir in tree_P2
schrieb.
Aber das scheint nur zu funktionieren, wenn der Datensatz lokal (let tree_C :=…
) erstellt wird, nicht, wenn es mit Definition
definiert ist.
Aber Fixpoint
kann andere Definitionen gut durchsehen, z.B. durch list_P
. Also was ist das Besondere an Aufzeichnungen, und kann ich Coq akzeptieren tree_P3
?