Comment puis-je convaincre Coq que la fonction récursive donnée ci-dessous se termine? La fonction prend deux arguments inductifs. Intuitivement, la récursivité se termine car l'un ou l'autre argument est décomposé.
Plus précisément, la fonction prend deux arbres en entrée.
Inductive Tree :=
| Tip: Tree
| Bin: Tree -> Tree -> Tree.
Sur Trees, j'aime faire le style d'induction suivant.
Inductive TreePair :=
| TipTip : TreePair
| TipBin : Tree -> Tree -> TreePair
| BinTip : Tree -> Tree -> TreePair
| BinBin : TreePair -> TreePair -> TreePair.
Fixpoint pair (l r: Tree): TreePair :=
match l with
| Tip =>
match r with
| Tip => TipTip
| Bin rl rr => TipBin rl rr
end
| Bin ll lr =>
match r with
| Tip => BinTip ll lr
| Bin rl rr => BinBin (pair l rl) (pair lr r)
end
end.
La définition de TreePair est acceptée, mais la définition de la paire de fonctions génère le message d'erreur:
Error: Cannot guess decreasing argument of fix.
Je suis donc intéressé à savoir comment convaincre Coq de la résiliation.
pair
est bien définie. Coq n'est que le véhicule.Réponses:
Les définitions de points fixes de Coq nécessitent que les appels inductifs reçoivent un argument structurellement plus petit. Au fond, une construction fixpoint prend un seul argument: il n'y a pas de concept intégré d'une définition récursive sur deux arguments. Heureusement, la définition de Coq de structurellement plus petit inclut des types d'ordre supérieur, ce qui est extrêmement puissant.
Votre définition de point fixe à deux arguments suit un modèle simple: soit le premier argument devient plus petit, soit le premier argument reste identique et le deuxième argument devient plus petit. Ce modèle assez courant peut être géré par un simple correctif.
Pour les cas plus complexes, ou si vos goûts fonctionnent de cette façon, vous pouvez utiliser la récursivité plus proche de la façon dont elle est enseignée dans les cours de mathématiques, en construisant le point de repère à partir d'un calcul d'étape et d'un argument de bien-fondé distinct , en utilisant souvent une mesure entière . Vous pouvez également faire ressembler votre définition à un programme classique dans une langue non totale avec une terminaison distincte en utilisant le
Program
vernaculaire .la source
fix pair1 r
dans la deuxième branche du niveau supérieurmatch
(et bien sûr, adapte la première branche pour renvoyer un type de fonction en conséquence)?