Stellen Sie sich einen induktiven Typ vor, der an einer verschachtelten, aber streng positiven Position einige rekursive Vorkommen aufweist. Zum Beispiel Bäume mit endlicher Verzweigung mit Knoten, die eine generische Listendatenstruktur zum Speichern der Kinder verwenden.
Inductive LTree : Set := Node : list LTree -> LTree.
Die naive Art, eine rekursive Funktion über diese Bäume zu definieren, indem über Bäume und Baumlisten rekursiv verfahren wird, funktioniert nicht. Hier ist ein Beispiel mit der size
Funktion, die die Anzahl der Knoten berechnet.
Fixpoint size (t : LTree) : nat := match t with Node l => 1 + (size_l l) end
with size_l (l : list LTree) : nat := match l with
| nil => 0
| cons h r => size h + size_l r
end.
Diese Definition ist unkorrekt (Fehlermeldung auszugsweise):
Error:
Recursive definition of size_l is ill-formed.
Recursive call to size has principal argument equal to
"h" instead of "r".
Warum ist die Definition falsch r
formuliert , obwohl es sich eindeutig um ein Subterm handelt l
? Gibt es eine Möglichkeit, rekursive Funktionen für eine solche Datenstruktur zu definieren?
Wenn Sie die Coq-Syntax nicht fließend beherrschen: Ist LTree
ein induktiver Typ, der der folgenden Grammatik entspricht.
Wir versuchen die size
Funktion durch Induktion über Bäume und Listen zu definieren . In OCaml wäre das:
type t = Node of t list
let rec size = function Node l -> 1 + size_l l
and size_l = function [] -> 0
| h::r -> size h + size_l r
quelle
Antworten:
Was funktioniert
Wenn Sie die Definition des Fixpunkts in Listen innerhalb der Definition des Fixpunkts in Bäumen verschachteln, ist das Ergebnis gut typisiert. Dies ist ein allgemeines Prinzip, wenn Sie eine Rekursion in einem induktiven Typ verschachtelt haben, dh wenn die Rekursion einen Konstruktor wie folgt durchläuft
list
.Oder wenn Sie es vorziehen, dies knapper zu schreiben:
(Ich habe keine Ahnung, von wem ich es zuerst gehört habe; dies wurde sicherlich viele Male unabhängig voneinander entdeckt.)
Ein allgemeines Rekursionsprädikat
Im Allgemeinen können Sie das „richtige“ Induktionsprinzip
LTree
manuell festlegen . Das automatisch erzeugte InduktionsprinzipLTree_rect
lässt die Hypothese in der Liste weg, da der Induktionsprinzip-Generator nur nicht verschachtelte streng positive Ereignisse vom Typ Induktion versteht.Fügen wir die Induktionshypothese zu Listen hinzu. Um dies im rekursiven Aufruf zu erfüllen, nennen wir das Listeninduktionsprinzip und übergeben es dem kleineren Baum in der Liste.
Warum
Die Antwort auf das Warum liegt in den genauen Regeln für die Annahme rekursiver Funktionen. Diese Regeln sind zwangsläufig subtil, da es ein empfindliches Gleichgewicht zwischen dem Zulassen komplexer Fälle (wie dieser mit verschachtelter Rekursion im Datentyp) und Unzuverlässigkeit gibt. Das Coq-Referenzhandbuch enthält eine Einführung in die Sprache (die Berechnung induktiver Konstruktionen, die die Beweissprache von Coq ist), meist mit formal präzisen Definitionen. Wenn Sie jedoch die genauen Regeln für Induktion und Coinduktion wünschen, lesen Sie die Forschungsarbeiten. zu diesem Thema von Eduardo Giménez [1].
Fix
l
t
size
h
l
size_l
r
l
size_l
Der Grund, warum
h
strukturell nicht kleiner ist alsl
laut Coq-Interpreter, ist mir nicht klar. Soweit ich aus den Diskussionen über die Coq-Club-Liste [1] [2] weiß, handelt es sich um eine Einschränkung des Dolmetschers, die grundsätzlich aufgehoben werden könnte, aber sehr sorgfältig, um Inkonsistenzen zu vermeiden.Verweise
Cocorico, das nicht abschließende Coq-Wiki: Gegenseitige Induktion
Coq-Club Mailingliste:
Das Coq-Entwicklungsteam. Der Coq Proof Assistant: Referenzhandbuch . Version 8.3 (2010). [ web ] ch. 4 .
Eduardo Giménez. Codierung von geschützten Definitionen mit rekursiven Schemata . In Types'94: Types for Proofs and Programs , LNCS 996. Springer-Verlag, 1994. doi: 10.1007 / 3-540-60579-7_3 [ Springer ]
Eduardo Giménez. Strukturelle rekursive Definitionen in der Typentheorie . In ICALP'98: Proceedings of the 25. International Colloquium on Automata, Languages and Programming. Springer-Verlag, 1998. [ PDF ]
quelle
Dies ist offensichtlich ein spezielles Problem für Coq, da ich glaube, dass es bessere Möglichkeiten gibt, es mit einigen anderen Proof-Assistenten zu umgehen (ich sehe Agda an).
Anfangs dachte ich, dass dies
r
nicht als strukturell kleiner erkannt wurde, da es sich bei der Struktur nur um die induktive Definition handelt, die derzeit behandelt wirdFixpoint
: Dies ist also keineLTree
Unterfunktion, auch wenn es sich um einelist
Unterfunktion handelt.Wenn Sie jedoch die Verarbeitung der Liste erweitern, funktioniert Folgendes:
Oder da die Hilfsfunktion bereits in der Standardbibliothek vorhanden ist:
Um ehrlich zu sein, bin ich mir nicht sicher, warum diese von Coq akzeptiert werden, aber ich bin froh, dass sie es sind.
Es gibt auch eine Lösung, die nicht nur für Listen häufiger funktioniert: die Definition eines in sich geschlossenen induktiven Typs. In diesem Fall können Sie Ihre
size
Funktion manuell definieren . (mit zwei Fixpunkten)Beachten Sie, dass Sie bei Problemen mit komplexeren induktiven Definitionen ein Argument verwenden können, das die Größe verringert. Das ist möglich, aber umständlich für dieses Problem (und ich würde es wagen, für die meisten Probleme zu sagen)
quelle