Universität Karlsruhe (TH) Institut für Programmstrukturen und Datenorganisation

Überladung in Typsystemen

Dissertation

Martin Wehr

Referend: Prof. Dr. Martin Odersky

Koreferend : Prof. Dr. Jacques Calmet

31. Oktober 1997

ii

Inhaltsverzeichnis

1 Einführung 1

2 Hintergrund 9

2.1 Typsysteme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.1 Der typfreie Lambdakalkül . . . . . . . . . . . . . . . . . . . . 9 2.1.2 Der einfach getypter Lambdakalkül . . . . . . . . . . . . . . . 11 2.1.3 Das implizit getypte System mit Polymorphie . . . . . . . . . 12 2.1.4 Das explizit getypte System mit Polymorphie . . . . . . . . . 12 2.1.5 Zusätzliche Typkonstrukte . . . . . . . . . . . . . . . . . . . . 13

2.2 Parametrizität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2.1 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2.2 Das System . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.3 Algebraische Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.3.1 Begriffsdefinitionen . . . . . . . . . . . . . . . . . . . . . . . . 23 2.3.2 Einbettung in Programmkalküle . . . . . . . . . . . . . . . . . 26 2.3.3 Erweiterung der Parametrizität . . . . . . . . . . . . . . . . . 27 2.3.4 Algebraische Datenwerte . . . . . . . . . . . . . . . . . . . . . 28

2.4 Der Hindley/Milner Ansatz . . . . . . . . . . . . . . . . . . . . . . . 32 2.4.1 Das logische System . . . . . . . . . . . . . . . . . . . . . . . 33 2.4.2 Das algorithmische System . . . . . . . . . . . . . . . . . . . . 34 2.4.3 Das semantische Modell . . . . . . . . . . . . . . . . . . . . . 35

2.5 Andere Ansätze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.5.1 Wadler/Blott: Typklassen . . . . . . . . . . . . . . . . . . . . 37 2.5.2 Kaes: Typsysteme mit Constraints . . . . . . . . . . . . . . . 39 iv INHALTSVERZEICHNIS

2.5.3 Duggan/Cormack/Ophel: Überladung mit Kinds . . . . . . . . 41 2.5.4 Nipkow, Prehofer, Snelting: Typinferenz mit ordnungssortier-

ter Unifikation . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.5.5 Mark Jones: Erweiterung von Typklassen . . . . . . . . . . . . 46 2.5.6 Parametrische Typklassen . . . . . . . . . . . . . . . . . . . . 48 2.5.7 Andere Ansätze . . . . . . . . . . . . . . . . . . . . . . . . . . 50

3 Logisches System 53 3.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 3.2 System O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.2.1 Die Termsprache . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.2.2 Die Typsprache . . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.2.3 Das Regelsystem . . . . . . . . . . . . . . . . . . . . . . . . . 57

3.3 Ein Programmbeispiel . . . . . . . . . . . . . . . . . . . . . . . . . . 59

4 Algorithmisches System 63

4.1 Eigenschaften von System O . . . . . . . . . . . . . . . . . . . . . . . 68

4.1.1 Semantische Korrektheit . . . . . . . . . . . . . . . . . . . . . 69 4.2 Beweis der Typeigenschaften . . . . . . . . . . . . . . . . . . . . . . . 71

4.2.1 Erweiterte Unifikation . . . . . . . . . . . . . . . . . . . . . . 71 4.2.2 Terminierung von unify . . . . . . . . . . . . . . . . . . . . . . 74 4.2.3 Vollständigkeit und Korrektheit der erweiterten Unifikation . . 75

4.3 Korrektheit und Vollständigkeit der Typinferenz . . . . . . . . . . . . 83 4.3.1 Transformation von Herleitungen . . . . . . . . . . . . . . . . 84 4.3.2 Die Allgemeinheitsrelation auf Typothesen und Typschemata . 87 4.3.3 Eingeschränkte Substitution . . . . . . . . . . . . . . . . . . . 91 4.3.4 Beziehungen zwischen Aussagen . . . . . . . . . . . . . . . . . 96 4.3.5 Eigenschaften der Typisierung . . . . . . . . . . . . . . . . . 103 4.3.6 Korrektheit des syntaktischen Systems . . . . . . . . . . . . . 105 4.3.7 Vollständigkeit der Typinferenz . . . . . . . . . . . . . . . . . 108 5 Erweiterung des Überladungssystems 117

5.1 Das Terminationsproblem für Typkonstruktoren . . . . . . . . . . . . 119 5.1.1 Terminierungsresultate . . . . . . . . . . . . . . . . . . . . . . 121 5.1.2 Leere Constraints . . . . . . . . . . . . . . . . . . . . . . . . . 122

5.2 Das logische System O_{2} . . . . . . . . . . . . . . . . . . . . . . . . . 125 5.3 Musterpassung auf Typebene . . . . . . . . . . . . . . . . . . . . . . 127

5.3.1 Der explizite Überladungskalkül F_{O} . . . . . . . . . . . . . . . 129 5.3.2 Andere Ansätze . . . . . . . . . . . . . . . . . . . . . . . . . . 130

5.4 Operationale Semantik für Überladung . . . . . . . . . . . . . . . . . 133 5.5 Erweiterte Typinferenz . . . . . . . . . . . . . . . . . . . . . . . . . . 136

5.5.1 Erweiterte Normalisierung . . . . . . . . . . . . . . . . . . . . 137 5.5.2 Erkennung leerer Einschränkungen . . . . . . . . . . . . . . . 139 5.5.3 Behandlung von curried überladenen Funktionen . . . . . . . 141 5.5.4 Erweiterter Inferenzalgorithmus . . . . . . . . . . . . . . . . . 143

6 Schluß 147 6.1 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 6.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Danksagung

Ich möchte mich bei allen bedanken die beigetragen haben meine Dissertation fertigzustellen. An erster Stelle möchte ich mich bei Martin Odersky bedanken, in dessen Gruppe ich drei Jahre in Karlsruhe verbracht habe. Seine enorme Energie, Vielseitigkeit und wissenschaftlicher Hintergrund waren mir immer ein Ansporn und werden es bleiben. Auf Grund der Seminare und Vorlesungen an unserem Lehrstuhl bin ich mit Typtheorie und Semantik von Programmiersprachen in Kontakt gekommen. Dank seiner Geduld hatte ich die Freiheit mich in die Kategorientheorie zu vertiefen. Seine Einladung zur Mitarbeit an dem Überladungspapier gemeinsam mit Phil Wadler hat zum Thema der Arbeit geführt. Die Dissertation von Kung Chen hat die Inspiration zu den Beweisen der Arbeit gegeben.

Ich möchte mich auch bei Jaques Calmet für die unkomplizierte Zusammenarbeit während der Dissertation bedanken.

Bei meinen Kollegen in Karlsruhe die mich in vielfältiger Form unterstützt haben möchte ich mich bedanken. Besonders bei Christoph Zenger für die Freundschaft und interssierten Diskusionen, bei meinem Kollegen Christian Kemper für die angenehme Atmosphäre in unserem geteilten Büro, bei meinen Kollegen John Maraist und Hendrik Lock für die angenehme Zusammenarbeit, bai Martin Sulzmann für die lebhaften Diskusionen über Typtheorie.

Die Arbeit hätte nicht vollbracht werden können ohne die moralische Unterstützung von meiner Frau Uschi und meinen Eltern und Geschwistern.

Kapitel 1

Einführung

Motivation

Das getypte Programmieren in modernen Programmiersprachen hat sich als mächtige Methode zur Reduzierung der Fehlerraten in der Softwareproduktion erwiesen. Die Realisierung eines besonders flexiblen Typsystems mit zugehöriger Typinferenz ist die Zielrichtung der vorgelegten Arbeit. Das Neuartige der Arbeit ist eine Verbindung von parametrischer Polymorphie und Überladung. Bereits in der Sprache Haskell wurde wurde die Verbindung dieser Typsysteme realisiert, die Probleme dieses Ansatzes werden durch die Lösungen der Arbeit aufgehoben. Insbesondere ist der Nutzter der vorgeschlagenen Lösung von der Formulierung komplexer Typannotationen befreit, diese Arbeit erledigt die Typinferenz.

Typsicherheit

Die Idee des getypten Programmierens ist es, für jeden Ausschnitt eines Programms die zulässigen Operationen festzulegen. Falls z.B. ein Programmausschnitt als ganzzahliger Ausdruck erkannt wird, sind nur die arithmetischen Operationen darauf zulässig. Die Behandlung von Typen läßt sich in statische und dynamische Typprüfung aufteilen. Bei der dynamischen Typprüfung werden in der Laufzeitrepräsentation der Programmteile Typkennungen hinzugefügt. An Hand dieser Typkennungen wird dann vor Ausführung jeder Operation deren Zulässigkeit geprüft. Die Nachteile dieser Methode liegen auf der Hand. Zum einen ergeben die Typkennungen einen erhöhten Speicher- und Verwaltungsaufwand, zum anderen können Programmausführungen unvorhergesehen mit einer Typfehlermeldung abbrechen. Die statische Typprüfung löst diese Probleme, indem Sie die Zulässigkeit der Operationen eines Programms zur Übersetzungszeit prüft. Bei statischer Typprüfung entfällt also zusätzlicher Laufzeitaufwand bei Programmausführung. Wenn ein statisch getyptes Programm die Typprüfung bestanden hat, ist damit auch nachgewiesen, daß alle Operationen, die zur Laufzeit ausgeführt werden, zulässig sind.

Diese Form von Fehlerfreiheit eines Programms wird Typsicherheit genannt. Diese Gewißheit ist in dem Slogan ”wohlgetypte Programme können nicht fehlschlagen” ausgedrückt.

Getyptes Programmieren bietet also eine zusätzliche Fehlerprüfung an, aber durch die Festlegung der zulässigen Programme können auch die Ausdrucksmöglichkeiten des Programmierers eingeschränkt werden. Bei der Entwicklung einer getypten Programmiersprache ist also das Ziel, ein möglichst ausdruckskräftiges Typsystem zu finden.

Die vorliegende Arbeit beschäftigt sich mit statischer Typprüfung. Nachdem bei einem statischen Typsystem die gesamte Typprüfung zur Übersetzungszeit des Programms stattfindet, stellt sich die Frage nach der algorithmischen Entscheidbarkeit der Wohlgetyptheit eines Programms. Bei der Entwicklung einer statisch getypten Programmiersprache sind also die Grenzen der Entwurfsentscheidungen zwischen der Ausdrucksfähigkeit der Sprache und der Entscheidbarkeit der Typisierung abgesteckt.

Polymorphie

Eine wichtige Begriffsbildung der Typsysteme ist der Begriff der Polymorphie. Die wörtliche Bedeutung “Vielförmigkeit” des Begriffs Polymorphie drückt die Möglichkeit aus Algorithmen so zu formulieren, daß sie nicht nur durch ihre Definition festgelegt sind, sondern bei jeder Benutzung ihre Form anpassen. Die Bedeutung der Sprachen mit Polymorphie liegt in ihrer besonderen Ausdrucksstärke; denn Algorithmen können so formuliert werden, daß Sie vielfältig wiederverwendbar sind. Die verschiedenen Arten der Polymorphie sind die parametrische Polymorphie, die Untertyp-Polymorphie und die Überladung.

Die folgenden Beispiele erläutern die verschiedenen Ausprägungen der Polymorphie.

Parametrische Polymorphie Man betrachte die Operationen auf einem Stapel :

push : ∀α.stack α × α → α
pop : ∀α.stack α → α

Der Code für die Operationen kann unabhängig von der Kenntnis der Eintragstypen der Stapeleinträge geschrieben werden. Also arbeiten diese Operationen uniform auf jeder Instanz (d.h. Einsetzung eines konkreten Typs für den Parameter α). Mit einem einzigen Programmcode hat man also sowohl Stapel von Zahlen als auch Stapel von Zeichenketten behandelt. Diese Uniformität von Algorithmen in Typparametern wird parametrische Polymorphie genannt.

Untertyp-Polymorphie Man betrachte ein graphisches System, welches in einer objektorientierten Sprache implementiert sei. In diesem System gebe es den Typ BildElement welcher die Methode anzeigen(x:Int, y:Int) kennt, zur Anzeige des Bildelements auf der Position mit den Koordinaten (x,y). Sei Objekt X ein BildElement dann ist der Aufruf X.anzeigen(0,0) wohlgetypt. Der Methodenaufruf wäre aber auch zulässig, wenn X den Typ Kreis oder Dreieck hätte und diese Typen die Methode anzeigen behandeln könnten. Bei einem System mit Untertyp-Polymorphie gibt es eine Beziehung zwischen Typen; die Untertypbeziehung. Kern des Typsystems ist die Regel, daß an Stelle eines Wertes eines bestimmten Typs auch jeder Wert eines Untertyps dieses bestimmten Typs einsetzbar ist.

Überladung Arithmetik, Gleicheitsprädikate und Ausgabefunktionen sind Operationen, die auf verschiedenen Arten von Daten mit verschiedenen Algorithmen definiert sind; diese Operationen sind also überladen. Zum Beispiel läßt sich die Operation addition auf den Typen Zahl, Matrix und Polynom definieren. Für jeden dieser Typen ist aber ein eigener Algorithmus zu schreiben. Wenn die Operation addition in einem Programm verwendet wird ist also spätestens zur Laufzeit eine Instanzselektion durchzuführen die den passenden auszuführenden Code für die Addition auswählt. Bei der Überladung wird also ein Name mit mehreren Codes überladen, wobei die Aufgabe des Typsystems in der Auflösung der Überladung besteht.

Die praktische Relevanz dieser Typdisziplinen ergibt sich bei einem Blick auf das Paradigma der Objektorientierung. Die Objektorientierung verfolgt zwei Ziele. Zum einen führt sie ein Entwurfsparadigma ein das um den Objektbegriff zentriert ist, zum anderen wird damit die Wiederverwendbarkeit von Programmteilen angestrebt. Auch die Polymorphie führt in hohem Maße zu einer vielseitigen Wiederverwendbarkeit.

Die folgenden Erläuterungen verdeutlichen den Zusammenhang zwischen Objektorientierung und Polymorphie. Der Code einer Methode ist durch den Methodennamen noch nicht festgelegt. Erst an Hand des aufgerufenen Objekts wird die Codeselektion durchgeführt. Damit ist Methodenauswahl ein Beispiel für Überladung in objektorientierten Sprachen. Falls eine bestimmte Methode auf ein Objekt X angewendet wird, ist die Typkorrektheitsforderung nur, daß diese Methode bekannt ist. Die Anwendbarkeit von Methoden wird durch Untertypen modelliert. Falls ein Programmteil, wie z.B. eine Stape, uniform für alle Instanzen formuliert werden kann, sollte diese Ausdruckmöglichkeit in einer Sprache mit Zielrichtung auf wiederverwendbaren Code auch existieren.

Grundlage

Eine getypte Sprache ist besonders einfach zu benutzen wenn der Programmierer keine Typangaben in sein Programm schreiben muß und der Übersetzer die Typisierung vornimmt oder Typfehler erkennt. Ein solches Verfahren wird Typinferenz genannt. Kern der meisten Typsysteme mit Typinferenz ist das bekannte Hindley/Milner Typsystem [Mil78] (kurz: HM-System) zur Behandlung der parametrischen Polymorphie. Das HM-System ist dreigeteilt in das logische System, das algorithmische System und das semantische Modell. Die Programme im HM-System basieren auf dem λ-Kalkül, also dem Kern funktionaler Programmiersprachen. Das logische System definiert formal die Herleitung einer Wohlgetyptheitsbeziehung zwischen einem Programm und einem Typ, es wird also der Wohlgetyptheitsbegriff geprägt. Dabei sind die Regeln des logischen Systems nach den Ausdrucksmitteln der Typen organisiert. Das algorithmische System ist nach den Ausdrucksmitteln der Programmiersprache organisiert. Das algorithmische System ist die formale Beschreibung des Typisierungsvorgangs wie er zur Übersetzungszeit einer statisch getypten Sprache stattfindet. Für ein gegebenes Programm berechnet also das algorithmische System den dazugehörigen Typ oder stellt einen Typfehler fest. Nun läßt sich der Zusammenhang zwischen dem logischen System und dem algorithmischen System untersuchen; es geht also um den Zusammenhang zwischen dem Begriff der Wohlgetyptheit und der Typisierungsberechnung zur Übersetzungszeit. Offensichtlich erwartet ein Programmierer, daß ein Programm, das den Typisierungstest bestanden hat wohlgetypt ist. Formal bedeutet das, daß jeder Berechnung des algorithmischen Systems eine Herleitung der selben Wohlgetyptheitsbeziehung im logischen System entspricht. Dieser Zusammenhang wird Korrektheit der Typinferenz genannt. Wie der Begriff Polymorphie schon besagt, ist es möglich, daß ein Programm mit vielen Typen in Wohlgetyptheitsbeziehung steht. Kern dieser Vielfalt ist die Eigenschaft der Typen bis auf freie Parameter festgelegt zu sein. Ein neuer Typ kann aus der Ersetzung der freien Parameter durch Typen hervorgehen, in diesem Fall wird der ursprüngliche Typ allgemeiner als der neue Typ genannt. Mit der Allgemeinheitsbeziehung lassen sich die Typen ordnen. Ein Programmierer ist daran interessiert, daß der Übersetzer für sein Programm denjenigen Typ berechnet, der bei der Benutzung des Programms die größte Flexibilität bietet. Das bedeutet für das Typsystem, daß der Typ, den das algorithmische System für ein Programm berechnet, allgemeiner ist als jede mögliche Typisierung des selben Programms im logischen System. Dieser Zusammenhang zwischen den Systemen wird Vollständigkeit der Typinferenz genannt. Die Eigenschaft, den allgemeinsten Typ in dem algorithmischen System zu berechnen, wird prinzipielle Typeigenschaft genannt. Die Aufgabe des semantischen Modells ist es, jedem Programm eine mathematische Bedeutung zu geben. So wird in dem Modell z.B. einer Funktion die Abbildung zwischen ihren Eingaben und Resultaten zugewiesen. Der Anwendung einer unzulässigen Operation wird im Modell ein Fehlerelement zugewiesen. Ein wichtiger Punkt des semantischen Modells ist die Verschiedenheit des Fehlerelements und des Elements zur Benennung der Divergenz einer Berechnung. Mit dieser Begriffsbildung läßt sich mathematisch präzise der Typsicherheits-Satz aufstellen : das Modell kann keinem Programm, für das in dem logischen System eine Wohlgetypheitsbeziehung hergeleitet werden kann, das Fehlerelement zuweisen. Mit dem Beweis dieses Satzes ist dem Prinzip des getypten Programmierens ”wohlgetypte Programme können nicht fehlschlagen” — eine mathematische Bedeutung gegeben.

Resultate

Ziel der vorliegenden Arbeit ist es, zu einer Verbindung von parametrischer Polymorphie und Überladung zu gelangen. Dabei sollen die Begriffsbildungen des HM-Systems als Leitlinie dienen. Wir entwickeln also ein Typsystem, genannt System O, für das ein logisches System, ein algorithmisches System und eine Semantik angegeben wird. Danach zeigen wir die Korrektheit und die Vollständigkeit der Typinferenz und die Typsicherheit. Eine Möglichkeit, das Problem von Überladung und parametrischer Polymorphie mit Typinferenz zu behandeln, ist der Ansatz der Typklassen [WB89], wie er in der Sprache Haskell realisiert wurde. Dieser Ansatz bietet ein ausdrucksmächtiges Typsystem, in dem nur wenige Typannotationen notwendig sind. Jedoch ist die Semantik für Typklassen noch kaum verstanden, da die Bedeutung des Programms von dem Beweis der Typisierung abhängig ist [HHJW96], was zu komplizierten Kohärenzargumenten führt [Jon92]. Ein weiteres Problem der Typklassen ist, daß die prinzipielle Typeigenschaft nicht erfüllt ist. Das Fehlen der Eigenschaft besagt die Unmöglichkeit der vollen Typinferenz; der Benutzer muß manchmal zur Typisierbarkeit Typannotationen in das Programm einfügen. Eine weitere Einschränkung ergibt sich für die möglichen Formen der Typen bei Verwendung von Typklassen. Für alle möglichen Instanzen eines überladenen Programmelements muß der Programmierer einen allgemeinsten Typ als Deklaration einer Typklasse angeben. Die Einschränkung der Vielfalt ergibt sich also dadurch, daß sich alle Typen für Instanzen von einem einzigen Typ herleiten lassen müssen. Die Resultate der vorliegenden Arbeit lösen diese Probleme. Diese Resultate wenden sich an Entwickler von Programmiersprachen, die in der vorliegenden Arbeit neue Lösungen und Methoden zur Weiterentwicklung finden. Zielrichtung der Resultate ist es Programmierern eine Steigerung der Produktivität und der Fehlerfreiheit ihrer Produkte zu ermöglichen. Zusammenfassend lassen sich der Hauptresultate wie folgt darstellen:

einfache Nutzung Wir konnten die erste Methode zur Typinferenz einer Sprache angeben, deren Typsystem die parametrische Polymorphie und die Überladung enthalten. Ein Programmierer muß sich also bei der Nutzung der Programmiersprache niemals Typannotationen in das Programm einfügen, denn der Übersetzer kann seine Aufgabe immer selbständig erledigen. Im Gegensatz dazu gibt es Programme in der Sprache Haskell welche der Übersetzer erst nach dem Einfügen von Typannotationen behandeln kann. Ein Haskellprogrammierer hat desweiteren die Pflicht für jede Nutzung der Überladung ein allgemeinstes Typschema anzugeben (Eine Spezifikation der Typklasse ist notwendig). Die Typisierung in Haskell ist also eine Typrekonstruktion im Gegensatz zu der Typinferenz welche in der Arbeit vorgestellt wird.

Ausdrucksstärke Wir haben das erste System zur Verbindung von parametrischer Polymorphie und Überladung ohne syntaktische Einschränkungen der Instanztypen vorgestellt.

Bei der Nutzung der Überladung kann der Programmierer für ein Programmelement mehrere durch die Typen unterschiedene Algorithmen angeben. Diese Algorithmen werden die Instanzen des Programmelements (z.B. einer Funktion) genannt. Bisher wurden die Ausdrucksmöglichkeiten für überladene Programme dadurch eingeschränkt, daß die Typen für die Instanzen bestimmte syntaktische Einschränkungen einhalten mußten. Die syntaktischen Einschränkungen waren nötig, um das Funktionieren der Typinferenz zu garantieren. Wenn ein Programm dann als nicht typisierbar von einem Inferenzmechanismus abgelehnt wurde ergab sich die Frage nach der semantischen Begründung dieser Entscheidung. Die Untersuchung dieses Fehlermeldungsverhalten führt zu einer Analyse der algebraischen Datentypen und zur Erweiterung der Modelleigenschaft Parametrizität. Als Resultat ergibt sich dann eine semantisch begründete Erweiterung der Typinferenz. Die syntaktischen Einschränkungen der Instanztypen wurden also aufgehoben.

In [Hen93] wurde allerdings gezeigt, daß die Typinferenz für parametrisch polymorphe rekursive Funktionen unentscheidbar ist. Das führt zu einer Einschränkung jeder Programmiersprache welche die Sprachmittel Polymorphie und Rekursion anbietet. Die praktische Lösung des Problems schränkt die rekursive Nutzung von polymorphen Programmelementen (z.B. Funktionen) zu einer monomorphen Nutzung ein. Dieser prinzipiellen Einschränkung von polymorphen Sprachen ist auch in der vorgestellten Ansatz unterworfen.

klare Bedeutung Wir konnten erstmals eine kompositionale Semantik für eine Sprache angeben, die parametrische Polymorphie und Überladung verbindet. Eine Semantik ist dann kompositional, wenn die Zuordnung der mathematischen Bedeutung zu einem Programm einfach an Hand der syntaktischen Struktur des Programms vorgenommen werden kann. Diese Semantik kann also unabhängig von der Typisierungsherleitung die Bedeutung von Programmen angeben. Damit konnte der Beweis der semantischen Korrektheit geführt werden als ein erweiterter Slogan “wohlgetypte überladene Programme können nicht fehlschlagen”

Überblick

In Kapitel 2 werden die Begriffe und Methoden erklärt, auf denen die Arbeit basiert. In Abschnitt 2.5 werden Vergleiche zu anderen bekannten Ansätzen angestellt. Es folgt das Kapitel 3 zur Beschreibung des logischen Systems. Kapitel 4 ist ein Schwerpunkt der Arbeit. In diesem Kapitel wird die Typinferenz vorgestellt, die wesentlichen Begriffe formalisiert und die Kernaussagen für die Typinferenz bewiesen. In Kapitel 5 wird der Ansatz zur Behandlung von überladenen Funktionen so erweitert, daß eine Aufhebung der syntaktischen Einschränkungen für Instanztypen resultiert. Die Darstellung des logischen Systems (Kapitel 3) ist auch in dem gemeinsamen mit Philip Wadler und Martin Odersky geschriebenen Konferenzpapier [OWW95] zu finden. Die Beweise der Korrektheit und Vollständigkeit des algorithmischen Systems sind wurden auch in dem technischen Bericht [WO96] aufgeschrieben.

8 KAPITEL 1. EINFÜHRUNG

Hintergrund

2.1 Typsysteme

Alle Sprachen welche in der vorliegenden Arbeit betrachtet werden sind funktionale Programmiersprachen. Das Paradigma der funktionalen Programmiersprachen sagt aus, daß Funktionen wie Daten behandelt werden können. Also können Funktionen als Parameter oder als Resultate verwendet werden. Der Kern aller funktionaler Programmiersprachen ist der von Church entdeckte Lambdakalkül. Der vorliegende Abschnitt faßt zum großen Teil die Darstellung von Barendregt [Bar92] zusammen.

2.1.1 Der typfreie Lambdakalkül

Ein Lambdaterm ist gegeben durch die Grammatik

e ::= x | c | λx.e | ee′

Dabei wird x eine Variable genannt und der Kalkül kann beliebig mit Konstanten c angereichert werden (wir werden später die benutzerdefinierte Anreicherung mit algebraischen Datenwerten betrachten). Der Ausdruck λx.e heißt Abstraktion und stellt eine Funktionsdefinition dar in welcher x der formale Parameter der Funktion ist und e der Körper der Funktion ist. Die Funktionsanwendung wir Applikation genannt und ist durch den Ausdruck ee′ beschrieben wobei e die Funktion darstellt und e′ der aktuelle Parameter ist der übergeben wird. Jede Variable welche in einer Abstraktion auftritt wird gebunden genannt sonst wird sie frei genannt. Die Menge der freien Variablen zu zu einem Term ist strukturell definiert als :

fv(e) = \{ \begin{matrix}\{x\} & für e = x \\ fv(e′) \ \{x\} & für e = λx.e′ \\ fv(e′) ∪ fv(e′′) & für e = e′e′′ \end{matrix}

Bei Umbenennung der gebundenen Variablen eines Lambdaterms entsteht per Definition wieder derselbe Term. Ein Term des Lambdakalküls stellt also ein funktionales Programm mit Funktionsdefinitionen und Funktionsaufrufen dar. Die Programmausführung wird in dem Kalkül durch Termreduktion beschrieben. Es gibt nur eine Reduktionsregel (die β-Regel) die durch strukturelle Erweiterung auf alle Terme ausgedehnt wird.

(λx.e)e′ ⟶^{β} [e′/x]e

Der Term auf der linken Seite wird (λx.e)e′ wird Redex genannt es handelt sich also um eine Funktion λx.e mit formalen Parameter x und aktuellem Parameter e′ welcher der Funktion übergeben wird. Der Reduktionsschritt besteht aus der Ersetzung des formalen Parameters x durch den aktuellen Parameter e′ (also der Substitution [e′/x]) in dem Funktionskörper e. Damit der Bindungszustand von Variablen bei einer Reduktion konstant bleibt fordern wir, daß die Namen der gebunden Variablen paarweise verschieden zu den freien Variablen des Redex sind. Durch die strukturellen Regeln wird die Reduktion so auf Terme fortgesetzt, daß überall in einem Term eine Reduktion stattfinden kann.

\frac{e →^{β} e′}{ee′′ →^{β} e′e′′}  \frac{e →^{β} e′}{e′′e →^{β} e′′e′}  \frac{e →^{β} e′}{λx.e →^{β} λx.e′}

Ein Term der nicht weiter reduziert werden kann ist in Normalform. Wenn ein funktionales Programm als Lambdaterm dargestellt wird, dann entspricht die Reduktion zur Normalform einer terminierenden Berechnung des Programms. Eine schöne Eigenschaft des Lambdakalküls ist die Church-Rosser-Eigenschaft die besagt, daß die Auswertungsreihenfolge (also die Auswahl der Redexe während der Reduktion) beliebig sein kann in einer terminierenden Berechnung.

Church-Rosser Eigenschaft

Sei ein Term e gegeben und die Reduktionen e →^{∗} e′ und e →^{∗} e′′ dann gibt es einen Term e′′′ mit den Reduktionen e′ →^{∗} e′′′ und e →^{∗} e′′′. Hierbei wurde für →^{∗} der reflexive transitive Abschluß der β-Relation →^{β} genommen.

Von Church wurde gezeigt, daß sich mit dem Lambdakalkül alle Berechnungen codieren und durchführen lassen welche sich mit der Turingmaschine berechnen lassen. Nach der Churchen These lassen sich also im funktionalen Programmieren auf Basis des Lambdakalküls alle algorithmischen Berechnungen durchführen die berechenbar sind. Um eine funktionale Programmiersprache zu implementieren ist es nötig eine Auswertungsstrategie festzulegen. Die zwei Strategien Bedarfsauswertung und strikte Auswertung haben sich im funktionalen Programmieren durchgesetzt. Die Idee der Bedarfsauswertung ist, es die Argumente einer Funktion nur soweit benötigt auszuwerten. Bei der strikten Auswertungsstrategie wird dagegen erst das Argument ausgewertet und dann erst die Funktion aufgerufen. Falls also hierbei die Argumentauswertung divergiert, dann divergiert auch die Funktionsauswertung d.h. die Funktion verhält sich strikt gegenüber divergierenden Argumenten. Bei der Bedarfsauswertung kann dagegen mit Argumenten gerechnet werde welche eine unendliche Darstellung hätten falls die Funktion nur auf einen endlichen Teil des Arguments zugreift. Um eine möglichst natürliche und starke Programmäquivalenz einzuführen wird noch eine weitere Regel η eingeführt und strukturell auf alle Terme erweitert :

λx.(ex) ⟶_{η} e wenn x ∉ fv(e)

Eine starke Programmäquivalenz ergibt sich dann aus der Äquivalenzrelation welche über die βη-Relation gebildet wird. In dem nächsten Abschnitt wird gezeigt wie man mit Hilfe des Begriffs Parametrizität über die Programmäquivalenzen argumentieren kann.

2.1.2 Der einfach getypter Lambdakalkül

Die Typen des einfach getypten Lambdakalküls sind durch die folgende Grammatik gegeben :

τ ::= α | T | τ → τ′

Dabei sind α, β, γ Typvariablen für die später beliebige Typen eingesetzt werde können. Die Typkonstanten T können die Typsprache anreichern (z.B. Int als Typ für ganze Zahlen). Der Typ τ → τ′ benennt Funktionen welche Argumente vom Typ τ auf Resultate vom Typ τ′ abbilden. Eine Typisierung ist ein Ausdruck e : τ der besagt, daß der Term e den Typ τ besitzt. In dem einfach getypten Lambdakalkül geht es darum aus Annahmen über die Typisierung der freien Variablen eines Terms eine Aussage über die Typen des Terms herzuleiten. Eine Annahmen von Variablentypisierungen Γ wird Typothese genannt und ist eine Menge von x : τ Ausdrücken, wobei jeder Variablenname x höchstens einmal in Γ auftreten kann. Die Menge der Variablen in Γ wird mit dom(Γ) notiert. Eine Typisierungsaussage hat die Form Γ ⊢ e : τ wobei fv(e) ⊆ dom(Γ). Der einfach getypte Lambdakalkül kann nun als logisches System in Form von 3 Regeln gegeben werden.

(T AUT)  Γ ⊢ x : τ (wenn x : τ ∈ Γ)

(→ I)  \frac{Γ, x : τ ⊢ e : τ′}{Γ ⊢ λx.e : τ → τ′}

(→ E) \frac{Γ ⊢ e : τ′ → τ  Γ ⊢ e′ : τ′}{Γ ⊢ e e′ : τ}

Bei einem Typsystem interessieren wir uns für zwei Eigenschaften. Zuerst die Entscheidbarkeit der Typisierungsaussage und als zweites die Berechenbarkeit der der Typisierung. Die Entscheidbarkeit der Typisierung sagt aus, daß es bei gegebener Typothese Γ, Term e und Typ τ entscheidbar ist ob die Aussage Γ ⊢ e : τ in dem System herleitbar ist. Die Berechenbarkeit der Typisierung sagt aus, daß aus einer gegebenen Typothese Γ und Term e ein Typ τ berechenbar ist, so daß die Aussage Γ ⊢ e : τ im System herleitbar ist. Typsysteme mit berechenbarer Typisierung können also zur Grundlage einer Programmiersprache dienen da zur Übersetzungszeit die Typisierung vorgenommen werden kann.

2.1.3 Das implizit getypte System mit Polymorphie

Nun wollen wir den einfach getypten Lambdakalkül zum System λ2 erweitern. Dieser Kalkül formalisiert den Begriff der parametrischen Polymorphie. In diesem Kalkül wir der Syntax des einfach getyptypten Lambdakalkül nur in der Typsprache um die polymorphen Typen ∀α.τ erweitert.

\begin{aligned}e & ::= & x | c | λx.e | ee′ \\ τ & ::= & α | T | τ → τ′ | ∀α.τ \end{aligned}

Die parametrische Polymorphie ergibt sich daraus, daß universell quantifizierte Typvariablen α z.B. in dem Typ ∀α.τ beliebig instantiiert werden können. Das System λ2 enthält die selben Regeln als der einfach getypte Lambdakalkül mit zusätzlichen Regeln welche die Quantifizierung (∀I) und die Instantiierung (∀E) von Typen behandeln

(∀I) \frac{Γ ⊢ e : τ  (α ∉ tv(Γ))}{Γ ⊢ e : ∀α.τ}  (∀E) \frac{Γ ⊢ e : ∀α.τ}{Γ ⊢ e : [τ′/α]τ}

In [Bar92] wird gezeigt, daß aus der Entscheidbarkeit der Typisierung die Berechenbarkeit der Typisiserung folgt. Die Frage nach der Entscheidbarkeit der Typisierung ist jedoch eines der“erstaunlichen offenen Probleme” nach einem Zitat von Robin Milner.

2.1.4 Das explizit getypte System mit Polymorphie

Das System F zur expliziten Darstellung von parametrischer Polymorphie ist eine Entdeckung von Reynolds [Rey74] und Girard [Gir72]. System F ist ein explizit getypter Kalkül da der formale Parameter x bei einer Abstraktion λx : τ.e immer explizit mit einer Typannotation eingeführt werden muß. Daraus ergibt sich, daß die Typsprache auch auf Termebene verwendet wird. Es werden also korrespondierende Termformationen zu den Quantoren Regel eingeführt um explizit Quantifikation und Instantiierung sichtbar zu machen. Relativ zu dem System λ2 wird also in System F nur die Termsprache erweitert.

\begin{aligned}e & ::= & x | c | λx : τ .e | ee′ | Λα.e | eτ \\ τ & ::= & α | T | τ → τ′ | ∀α.τ \end{aligned}

In System F gibt es Abstraktion und Applikation nicht nur für Terme sondern auch für Typen. Der Term Λα.e stellt eine Abstraktion über eine Typparameter α dar. Mit dem Ausdruck eτ kann ein Typargument an eine solche Funktion übergeben werden. Diese neue Form von Funktion und Argument wird zusammen mit einer neuen Reduktionsregel β2 eingeführt, so daß ähnlich zu einem Funktionsaufruf mit Termargumenten ein Funktionsaufruf mit Typargumenten ausgewertet wird.

(Λα.e)τ ⟶^{β2} [τ/α]e

Das logische System F ist eine Abänderung von λ2 nur bei den Quantorenregeln.

(∀I) \frac{Γ ⊢ e : τ  (α ∉ tv(Γ))}{Γ ⊢ Λα.e : ∀α.τ}  (∀E) \frac{Γ ⊢ e : ∀α.τ}{Γ ⊢ eτ′ : [τ′/α]τ}

2.1.5 Zusätzliche Typkonstrukte

Wir wollen hier noch zwei Typkonstrukte behandeln welche im Rahmen der Arbeit anklingen.

Rekursive Typen

Mit rekursiven Typen lassen sich Typen beschreiben die nicht mehr endlich syntaktisch zu präsentieren sind. Zu den bekannte Typformationen des Lambdakalküls kommt das Konstrukt μα.τ hinzu. Damit wird ein Typ benannt welcher syntaktisch als regulärer Baum dargestellt werden kann durch unendliche Selbsteinsetzung [μα.τ/α]τ. Ein Beispiel für die praktische Nutzung dieses Konstrukts sind Listen oder Bäume welche sich mit Hilfe dieser Konstrukte formulieren lassen. Seien die Typformationen weiter mit dem kartesischen Produkt × zur Bildung von Tupeln angereichert wobei 1 für den Typ der leeren Tupel () : 1 steht. Weiter soll als Typformation noch die disjunkte Summe + zur Bildung von markierten Werten zur Verfügung stehen. Mit diesen Mitteln sind folgende Definitionen möglich :

Listen über Einträge des Typs τ  μα.1 + τ × α
Binärbäume mit Blatteinträgen des Typs τ μα.τ + α × α

Die algebraischen Datentypen welche in funktionalen Sprachen wie ML oder Haskell angeboten sind aber noch ausdrucksstärker als rekursive Typen. Die Spezifikation des Typs Br a = Lft a | Rght Br Br a läßt sich mit rekursiven Typen nicht modellieren. Der Grund für diesen Fehlschlag liegt darin, daß die Wertmenge zu einem rekursiven Typ eine reguläre Baumsprache bildet, während die Wertmengen von algebraischen Datentypen eine kontextfreie Baumsprache bilden. Die Wertmenge zu dem Beispielstyp Br a ist die Klammersprache welche nicht regulär ist.

Kinds

Wir haben gesehen, daß der explizite Lambdakalkül mit parametrischer Polymorphie (System F) durch Einführung der Abstraktion und Applikation von Typen auf Termebene entsteht. Wenn wir ein System betrachten welches auf Typebene die Operation des Zusammensetzens von Typen ausdrücken kann, dann erhalten wir ein Typsystem mit Kinds. Die Kinds können als Typisierung der Typnamen aufgefaßt werden, bei den Beispielen Int : ∗ und List : ∗ → ∗ gibt der Kind ∗ an, daß Int ein Typ ist während ∗ → ∗ angibt, daß List ein Typkonstruktor ist welcher ein Typargument benötigt. Formal werden Kinds als dritte Ebene zu den Termen und Typen in die Sprache eingeführt zusammen mit einer Abstraktion und Applikation auf der Typebene. Die Kindsprache bestehend nur aus Kinds und Typen, hat also ähliche Ausdrucksmöglichkeiten als die Typen und Terme des einfach getypten Lambdakalküls. Man beachte, daß in der Kindsprache nur die Kindkonstante ∗ zur Verfügung steht; dem steht eine Vielzahl von Typvariablen im einfach getypten Lambdakalkül entgegen.

\begin{aligned}τ & ::= & α | T | τ → τ′ | λα : κ.τ | ττ \\ κ & ::= & ∗ | κ → κ′ \end{aligned}

Die Ausrücke κ sind die Kinds und geben Auskunft über die Art der konsumierten Argumente eines Typkonstruktors. Eine Erweiterung einer Programmiersprache um Kinds wurde mit den Funktorklassen von Jones [Jon93] betrachtet. Duggan [DCO96] bettet Überladung mit Hilfe von Kinds in einen Kalkül ein.

Die algebraischen Datentypen lassen sich mit kinded Typrekursion modellieren. Das Beispiel der Klammersprache

                    Br a = Lft a | Rght Br Br a

läßt sich in dem Term

μt : ∗ → ∗.(λα : ∗.α) + (λα : ∗.t(tα))

darstellen.

2.2 Parametrizität

In dem Abschnitt 2.1 wurde die parametrische Polymorphie in einem logischen System dargestellt. Damit wurden formal polymorphe Programme und ihre operationale Semantik bestimmt. Nun soll noch die Bedeutung der parametrischen Polymorphie formal festgelegt werden; eben die Eigenschaft, daß Algorithmen für bestimmte Argumente uniform arbeiten selbst wenn diese Argumente verschiedene Typen besitzen. Hier wird also nach einem Begriff gesucht welcher die Eigenschaft jeder guten Semantik für parametrische Polymorphie ist. Strachey [Str67] hat diese Eigenschaft als erster informell beschrieben und den Begriff Parametrizität geprägt. Reynolds ist es mit der formalen Darstellung der expliziten parametrischen Polymorphie gelungen die Parametrizität als relationale Parametrizität zu formalisieren [Rey83, MR91]. Die Grundlage dieses Abschnitts sind die Darstellungen aus [PA93, Wad93, Mai91] dort wird die relationale Parametrizität als Erweiterung des logischen Systems entwickelt, so daß eine formale Argumentation mit relationaler Parametrizität möglich ist. Nachdem viele Bereiche aus Logik, Typtheorie und Programmsemantik mit kategoriellen Mitteln sehr klar darstellbar sind, wurde auch ein kategorisches Konzept der Parametrizität entwickelt [BFSS90, Fre93, RR94]. Schon häufig wurde bei der kategorischen Behandlung von Begriffen der Programmiersprachen beobachtet, daß die notwendigen Strukturen nicht neu entwickelt werden müssen sondern bereits von den Gründern der Kategorientheorie beschrieben wurden. Diese Beobachtung gilt auch hier; Kern des kategorischen Parametrizitätsbegriffs sind die dinaturalen Transformationen die auch schon in dem Grundlagenbuch von Saunders Mac Lane beschrieben wurden [Lan72]. Wichtig für unsere Arbeit ist auch noch die Darstellung von Longo [Lon95] in der Parametrizität als Modelleigenschaft untersucht wird, und ein Zusammenhang mit der Überladungspolymorphie durch den λ&-Kalkül vorgeschlagen wird. Wir wollen hier den praktischen Nutzen der Parametrizität herausheben. Die Theorie der Parametrizität läßt ein formales Argumentieren über Programmäquivalenzen zu. Das Besondere dieser Theorie ist es, daß die Programmäquivalenzen nicht aus den Programmen selbst hergeleitet werden sondern aus ihren Typen. In dem Abschnitt 5.1 über explizite Überladung werden wir die Parametrizität auf Überladung erweitern. Die Erweiterung der Parametrizität auf algebraische Datentypen führt zu einem Kriterium um die Wohldefiniertheit von überladenen Funktionen aus Betrachtung der Typen zu garantieren. Die Erweiterung der Parametrizität auf Überladungspolymorphie führt zu einem Kriterium um bedeutungsleere Überladungseinschränkungen zu erkennen und bei Semantikerhaltung entfernen.

2.2.1 Beispiel

In dem Papier “Theorems for free” [Wad93] motiviert Wadler den Parametrizitätsbegriff durch folgendes Beispiel. Sei eine Funktion r gegeben, zu der nur deren Typ ∀α.List α → List α nicht aber deren Implementierung bekannt sei. So läßt sich an Hand des Typs sagen, daß die Funktion r die Einträge einer Argumentsliste nur umordnet, kopiert oder verwirft. Diese Aussage läßt sich in der folgenden Programmäquivalenz darstellen. Für jede Funktion a : T → T′ gilt die Gleichung :

(map a) ∘ r_{T} = r_{T′} ∘ (map a)

wobei map a : List T → List T′ die Funktion ist, welche eine Argumentliste List T nimmt und auf jedes Element der Liste die Funktion a anwendet und aus den Resultaten eine Liste List T′ produziert. Die Funktionen r_{T} und r′_{T} sind die Instanzen der parametrischen Funktion r für die Typkonstanten T oder T′. Weiter unten werden wir nach der formalen Darstellung der Parametrizität den Beweis dieser Kommutationsgleichung vorführen können.

2.2.2 Das System

Formeln und Relationen

Das System ist eine Erweiterung des System F um über Programmäquivalenzen und Beziehungen zwischen Programmen sprechen zu können. Die neuen Ausdrucksmöglichkeiten werden durch die Formeln ϕ ::= e =_{τ} e′ | R(e, e′) dargestellt. Weiter unten werden wir sehen, daß das Zeichen =_{τ} genau der βη-Äquivalenz von Termen des System F entspricht. Zusätzlich zu den Typvariablen α und den Termvariablen x : τ kann in diesem System über Relationenvariablen R ⊂ τ ×τ′ gesprochen werden. Dabei wird dann eine Relationsvariable R ⊂ τ × τ′ in einer wohlgeformten Formel als Relation zwischen Termen des Typs τ und Termen des Typs τ′ benutzt. Die Formelsprache wird mit den üblichen Quantoren über alle Arten von Variablen und den Verknüpfungen zwischen Formeln angereichert.

ϕ ::= … ∀α.ϕ | ∀x : τ.ϕ | ∀R ⊂ τ × τ′.ϕ
∃α.ϕ | ∃x : τ.ϕ | ∃R ⊂ τ × τ′.ϕ
ϕ ∨ ψ | ϕ ∧ ψ | ϕ ⊃ ψ

Aus den Formeln lassen sich wiederum definierbare Relationen zusammensetzen.

definierbare Relation ρ ::= (x : τ, y : τ′). ϕ[x, y]

Im obigen Fall wurde eine Relation zwischen den Typen τ und τ′ definiert was kurz als ρ ⊂ τ × τ′ notiert wird. Die folgenden definierten Relationen werden später benutzt : Die Gleichheitsrelation eq_{τ} ≡ (x : τ, y : τ′). x =_{τ} y und der Graph zu einer Funktion f : τ → τ′ ist definiert durch < f > ≡ (x : τ, y : τ′). fx =_{τ′} y.

Typen und Relationen

Wir werden die Konstruktoren für Typen zu Konstruktoren für Relationen erweitern. Durch strukturelle Erweiterung erhalten wir dann eine Konstruktion in der durch Ersetzung einer Typvariable mit einer Relation ein Typ zu einer Relation gewandelt wird. Dieses Sprachmittel wird im nächsten Abschnitt benutzt um das zentrale Parametrizitätsschema des Systems zu formulieren. Wir können den Konstruktor für Funktionstypen “→” auf Relationen erweitern. Seien die beiden Relationen ρ ⊂ τ_{1} × τ_{2} und ρ′ ⊂ τ_{1}′ × τ_{2}′ gegeben so definieren wir die zusammengesetzte Relation

ρ → ρ′ ⊂ τ_{1} → τ_{1}′ × τ_{2} → τ_{2}′

durch die Formel

f(ρ → ρ′)g ≡ ∀x : τ_{1}.∀y : τ_{2}. xρy ⊃ fx ρ′ gy

Sei eine definierte Relation ρ ⊂ τ ×τ′ gegeben, so daß in der definierenden Formel die Relationsvariable R ⊂ α × β auftreten kann. Dann definieren wir für die universelle Quantifikation ∀ eine Konstruktion mit folgender Signatur:

∀R ⊂ α × β.ρ ⊂ ∀α.τ × ∀β.τ′

Diese neue Relation wird durch folgende Formel definiert:

x(∀R ⊂ α × β.ρ)y ≡ ∀α.∀β.∀R ⊂ α × β.xα ρ yβ

Mit der Erweiterung von “→” und “∀” auf Relationen läßt sich nun strukturell eine neue Konstruktion definieren. Diese Konstruktion [ρ/α] besteht aus der Ersetzung von Typvariablen α durch definierte Relationen ρ ⊂ τ′×τ′′. Wenn diese Konstruktion auf einen Typ τ angewandt wird, entsteht eine neue Relation

[ρ/α]τ ⊂ [τ′/α]τ × [τ′′/α]τ

Die Konstruktion ist strukturell für jede Produktion der Typgrammaktik τ ::= α | τ → τ′ | ∀α.τ definiert. Sei also die definierte Relation ρ ⊂ τ′ × τ′′ gegeben so ist die neue Relation [ρ/α]τ wie folgt definiert :

Typvariable Wenn τ = α dann ρ falls τ ∈ Var aber τ ≠ α dann eq_{τ}.

Funktion Wenn τ = τ_{1} → τ_{2} dann [ρ/α]τ_{1} → [ρ/α]τ_{2}.

Quantor Wenn τ = ∀β.τ_{1} so kann immer angenommen werden, daß die gebundene Variable β und die freie Variable α verschieden sind, also β ≠ α dann gilt [ρ/α]τ = ∀R ⊂ β′ × β′′.[R/β, ρ/α]τ_{1}.

Zu einem Typ τ ist also strukturell die Relation [ ]τ ⊂ τ × τ gegeben durch die Ersetzung aller Typvariablen α durch die entsprechende Relation eq_{α}.

Regeln und Lemmas

Nun wollen wir das System ⊢^{R} beschreiben in dem Aussagen mit Hilfe der relationalen Parametrizität hergeleiten werden können. Eine Typothese Γ enthalte Einträge für getypte Termvariablen x : τ und getypte Relationsvariablen R ⊂ τ × τ′. Die Hypothese A enthalte eine Menge von Formeln ϕ. Die Aussage Γ; A ⊢^{R} ϕ bedeute, daß in dem System aus der Hypothese A die Formel ϕ hergeleitet werden kann. Die Regeln des Systems können in 3 Gruppen zusammengefaßt werden :

• Die Standardregeln für die logischen Verknüpfungen (∧, ∨, ⊃ , ∀, ∃).

• Axiome und Regeln zur Definition der Gleichheit =_{τ} .

• Ein Schema um relationale Parametrizität auszudrücken.

Die Gleichheit ist reflexiv und enthält die β und η Regeln, z.B. gelten die β-Regel und die η-Regel für Terme

\begin{matrix}⊢^{R} & ∀x : τ.((λx : τ.e)x =_{τ′} e) \\ ⊢^{R} & ∀α.∀β.∀f : α → β.((λx : α.fx) =_{α→β} f) \end{matrix}

und die Gleichheit ist eine Kongruenz auf den Termen

\begin{aligned}⊢^{R} (∀x : τ.e =_{τ′} e′) & ⊃ & λx : τ.e & =_{τ→τ′} & λx : τ.e′ \\ ⊢^{R} (∀α.e =_{τ} e′) & ⊃ & Λα.e & =_{∀α.τ} & Λα.e′ \end{aligned}

Die Relationen bleiben unter Substitution invariant

\begin{matrix}⊢^{R} ∀α.∀β.∀R ⊂ α × β.∀x, x′ : α.∀y, y′ : β. \\ R(x, y) ∧ x =_{α} x′ ∧ y =_{β} y′ ⊃ R(x′, y′) \end{matrix}

Das Schema für die relationale Parametrizität ist

⊢^{R} ∀x : ∀α.τ. x([ ]∀α.τ)x

Eine Auffaltung der definierten Relation [ ]∀α.τ führt zu

⊢^{R} ∀x : (∀α.τ). x(∀R ⊂ α′ × α′′.[R/α]τ)x

Eine Auffaltung der universell quantifizierten Relationen ∀R führt zu

⊢^{R} ∀x : (∀α.τ).∀α′.∀α′′.∀R ⊂ α′ × α′′. xα′([R/α]τ)xα′′

Also folgt bei Instantiierung eines polymorphen Terms x mit Typen welche durch eine Relation verbunden sind, daß auch die zwei erhaltenen Instanzterme wieder zueinander in Relation stehen; dies ist die Idee von Reynolds relationaler Parametrizität.

Die zwei folgenden Lemmas lassen sich in dem System ⊢^{R} herleiten Lemma 2.2.1 (Lemma der Identitätserweiterung) Sei ein Typ τ mit den freien Variablen \overline{α} gegeben, dann ist die folgenden Aussage herleitbar :

⊢^{R} ∀\overline{α}.∀x, y : τ.x([ ]τ)y ≡ x =_{τ} y

Kurzgesagt: die Relation [ ]τ die strukturell für den Typ τ definiert ist, ist äquivalent zu der Gleichheitsrelation =_{τ} die durch die Regeln und Axiome des Systems definiert ist.

Lemma 2.2.2 (Lemma der logischen Relation) Sei eine Typisierungsaussage x_{1} : τ_{1}, …, x_{n} : τ_{n} ⊢^{F} e : τ herleitbar im System F. Wenn \overline{α} die dabei verwendeten Typvariablen sind, so gilt

∀\overline{α}′.∀\overline{α}′′.∀\overline{R} ⊂ \overline{α}′ × \overline{α}′′.
∀x′_{1} : [\overline{α}′/\overline{α}]τ_{1}, …, x′_{n} : [\overline{α}′/\overline{α}]τ_{n}.
∀x′′_{1} : [\overline{α}′′/\overline{α}]τ_{1}, …, x′′_{n} : [\overline{α}′′/\overline{α}]τ_{n}.
(x′_{1}([\overline{R}/\overline{α}]τ_{1})x′′_{1}) ∧ ⋯ ∧ (x′_{n}([\overline{R}/\overline{α}]τ_{n})x′′_{n}) ⊃ [\overline{x}′/\overline{x}]e([\overline{R}/\overline{α}]τ)[\overline{x}′′/\overline{x}]e

Das Lemma der logischen Relationen ermöglicht es also bei gegebener Typisierungsaussage eine Erweiterung der Relation bei Termsubstitutionen zu rechtfertigen.

Typen und Funktionen

Die Theorie der Parametrizität spricht über die drei Begriffe Typen, Terme und Relationen. Bisher wurden bereits zwei Konstruktionen vorgeführt um jeweils zwei dieser Begriffe in Zusammenhang zu bringen. Mit definierbaren Relationen ließ sich aus Funktionstermen e : τ → τ′ die Relationen des zugehörigen Graphs < e > gewinnen. Durch die Erweiterung der Typkonstruktoren ließ sich aus einem Typ τ durch Einsetzung [R/α]τ eine neue Relation gewinnen. Hier schließt sich nun der Kreis indem aus einem Typ τ durch Einsetzung einer Funktion f : τ′ → τ′′ eine neue Funktion [f/α]τ konstruiert wird. Das Graphlemma (Lemma 2.2.3) bringt dann alle Konstruktionen in einen Zusammenhang.

Die nun folgende Begriffsentwicklung ist kategorisch motiviert. Wir werden nun die Begriffe Komposition, Identitätsmorphismus und Funktor entwickeln. Mit den Typen als Objekten und den Funktionstermen als Morphismen können wir eine Kategorie bilden. Dazu kann die Komposition von Morphismen wie üblich im funktionalen Programmieren beschrieben werden :

comp ≡ Λα.Λα′.Λα′′.λg : α′ → α′′.λf : α → α′.λx : α.g(fx)

anstatt comp ττ′τ′′gf schreiben wir abkürzend f ∘ g. Der Identitätsmorphismus ist durch die parametrische Identitätsfunktion gegeben.

id ≡ Λα.λx : τ.x

Für diese Definitionen können die kategoriellen Axiome f ∘ (g ∘ h) = (f ∘ g) ∘ h (Assoziativität der Komposition) und id∘f = f = f ∘id (Neutralität der Identität) im System hergeleitet werden.

Wir weisen jedem Auftreten einer Typvariable α im Typ τ eine Polarität zu. Das Auftreten der Variable wird positiv genannt, wenn der Pfad zu α geradzahlig oft auf der linken Seite des Typkonstruktors “→” vorbeiführt. Das negative Auftreten eine Typvariable wird gegensätzlich definiert. Zum Beispiel tritt in dem Typ α → β die Typvariable α negativ auf und die Typvariable β tritt positiv auf. Ein Typ τ wird polarisiert genannt wenn jede Typvariable α ∈ tv(τ) bei jedem Auftreten in dem Typ dieselbe Polarität hat. In einem polarisierten Typ kann also den Typvariablen eine Polarität zugewiesen werden anstatt ihrem Auftreten.

Im folgenden soll nun ein polarisierter Typ τ gegeben sein, so daß die Typvariablen \overline{α} nur positiv in dem Typ auftreten und die Typvariablen \overline{β} nur negativ auftreten, dies soll als τ[\overline{α}, \overline{β}] notiert werden. Zu diesem Typ läßt sich nun strukturell eine parametrische Funktion definieren welche entsprechend den Typvariablen Funktionsterme als Argumente nimmt. In kategorischen Begriffen handelt es sich um einen multivarianten Funktor welcher in den \overline{α} entsprechenden Argumenten kovariant ist und in den \overline{β} entsprechenden Argumenten kontravariant ist. Der zu τ gehörende Term hat dann folgenden Typ :

m_{τ} : ∀\overline{α}\overline{β}.∀\overline{α}′\overline{β}′.(\overline{α} → \overline{α}′) → (\overline{β}′ → \overline{β}) → (τ[\overline{α}, \overline{β}] → τ[\overline{α}′, \overline{β}′])

Wir haben dabei die Kurzschreibweise τ[\overline{α}′, \overline{β}′] für die Einsetzung [\overline{α}′/\overline{α}, \overline{β}′/\overline{β}]τ verwendet. Aus dem funktionalen Programmieren sind Funktionen dieser Art als map Funktionen bekannt. Strukturell ist die Funktion m_{τ} für die Fälle von τ wie folgt definiert:

m_{α}\overline{α}\overline{β}\overline{α}′\overline{β}′\overline{f}\overline{g}  = \begin{cases}f_{i} & wenn α die i-te Variable der Sequenz \overline{α} ist \\ g_{j} & wenn α die j-te Variable der Sequenz \overline{β} ist \\ id_{α} & sonst \end{cases}
m_{(τ[\overline{β},\overline{α}]→τ′[\overline{α},\overline{β}])}\overline{α}\overline{β}\overline{α}′\overline{β}′\overline{f}\overline{g} = λh : τ[\overline{β}, \overline{α}] → τ′[\overline{α}, \overline{β}].
(m_{(τ′[\overline{α},\overline{β}])}\overline{α}\overline{β}\overline{α}′\overline{β}′\overline{f}\overline{g}) ∘ h ∘ (m_{(τ[\overline{β},\overline{α}])}\overline{β}′\overline{α}′\overline{β}\overline{α}\overline{g}\overline{f})
m_{(∀γ.τ[\overline{α},\overline{β}])}\overline{α}\overline{β}\overline{α}′\overline{β}′\overline{f}\overline{g}  = λx : (∀γ.τ[\overline{α}, \overline{β}]).Λγ.(m_{τ[\overline{α},\overline{β}]}\overline{α}\overline{β}\overline{α}′\overline{β}′\overline{f}\overline{g}(xγ))

Für gegeben Funktionssequenzen \overline{e} : \overline{τ_{1}} → \overline{τ_{1}}′ und \overline{e}′ : \overline{τ_{2}}′ → \overline{τ_{2}} schreiben wir kurz τ[\overline{e}, \overline{e′}] : τ[\overline{τ_{1}}, \overline{τ_{2}}] → τ[\overline{τ_{1}}′, \overline{τ_{2}}′] für die Funktionsanwendung m_{τ} \overline{τ_{1}}\overline{τ_{2}}′\overline{τ_{1}}′\overline{τ_{2}}\overline{e}\overline{e}′, Durch Erzetzung von Typvariablen durch Funktionen ensteht also eine neue Funktion. In dem System können nun für die Definition von m_{τ} die Axiome eines Funktors hergeleitet werden.

τ[id\overline{α}, id\overline{β}]  = id_{τ[\overline{α},\overline{β}]}  (Erhaltung der Identität)
τ[\overline{f} ∘ \overline{f}′, \overline{g}′ ∘ \overline{g}] = τ[\overline{f}, \overline{g}] ∘ τ[\overline{f}′, \overline{g}′] (Multivarianz)

Um die Kontravarianz auch auf Relationen wiederspiegeln zu können definieren wir für eine gegebene Relation ρ ⊂ τ × τ′ die Relation ρ^{op} ≡ (y : τ′, x : τ).xρy. In dem System kann nun das Graphlemma bewiesen werden welches einen Zusammenhang zwischen Typen, Funktionen und Relationen darstellt.

Lemma 2.2.3 (Graphlemma) Sei ein Typ τ gegeben dessen freie Typvariablen \overline{α}, \overline{β} sind. Die Typvariablen \overline{α} treten nur positiv in dem Typ auf und die Typvariablen \overline{β} treten nur negativ in dem Typ auf. Dann gilt der Satz

∀\overline{α}\overline{β}.∀\overline{α}′\overline{β}′.∀\overline{f} : \overline{α} → \overline{α}′.∀\overline{g} : \overline{β} → \overline{β}′.(< τ[\overline{f}, \overline{g}] > = τ[< \overline{f} >, < \overline{g} >^{op}])

Allgemeine Kommutativität

Mit den Sätzen dieses Abschnitts wollen wir nun ein allgemeines Kommutativitätsprinzip für Funktionen in dem System mit relationaler Parametrizität herleiten. Sei ein Typ τ[\overline{α}, \overline{β}] gegeben, so daß seine freien Typvariablen in die positiv auftretenden \overline{α} und die negativ auftretenden \overline{β} getrennt seien. Wir wollen ein allgemeines Kommutativitätsgesetz für Funktionen des Typs r : ∀\overline{α}\overline{β}.τ → τ herleiten. Zuerst wenden wir das Parametrizitätsschema des Systems an und erhalten die Beziehung :

r(∀\overline{R} ⊂ \overline{α}′, \overline{β}′ × \overline{α}′′, \overline{β}′′.τ → τ)r

Wenn wir die Definitionen der Verknüpfungen ∀, → auf Relationen auffalten, erhalten wir das Gesetz

∀\overline{R} ⊂ \overline{α}′, \overline{β}′ × \overline{α}′′, \overline{β}′′.∀x : τ[\overline{α}′, \overline{β}′].∀y : τ[\overline{α}′′, \overline{β}′′].x([\overline{R}/\overline{α}, \overline{β}]τ)y ⊃ rx([\overline{R}/\overline{α}, \overline{β}]τ)ry

Nun läßt sich also eine beliebige Relationsequenz \overline{R} für die Variablen einsetzen. Nehmen wir die Funktionssequenzen \overline{f} : \overline{τ_{1}} → \overline{τ_{1}}′ und \overline{g} : \overline{τ_{2}}′ → \overline{τ_{2}} als gegeben an, so wollen wir die Relationsvariablen \overline{R} durch den Graph < \overline{f}, \overline{g} > ersetzen. Bei Einsetzung in den Typ τ ergibt sich die neue Relation [< \overline{f}, \overline{g} > /\overline{α}, \overline{β}]τ, diese Relation ist nach dem Graphlemma gleich dem Graph des entsprechenden Funktors < τ[\overline{f}, \overline{g}] > oder anders formuliert < m_{τ} \overline{f}\overline{g} >. Also erhalten wir bei dieser Einsetzung für beliebige \overline{f}, \overline{g} das Gesetz:

∀x.∀y.x(< m_{τ} \overline{f}\overline{g} >)y ⊃ rx < m_{τ} \overline{f}, \overline{g} > ry

Wenn wir nun die Definition des Graphen < . > einer Funktion auffalten erhalten wir

∀x.∀y.(m_{τ} \overline{f}\overline{g})x = y ⊃ (m_{τ} \overline{f}\overline{g})rx = ry

Wir eliminieren nun die Variable y durch Einsetzung und erhalten

∀x.(m_{τ} \overline{f}\overline{g})rx = r(m_{τ} \overline{f}\overline{g})x

Dies ist aber bereits die gesuchte Kommutationsgleichung

(m_{τ} \overline{f}\overline{g}) ∘ r = r ∘ (m_{τ} \overline{f}\overline{g})

Als einfaches Korollar ergibt sich nun der Beweis für das motivierende Beispiel in der Einleitung des Abschnitts. Sei also eine Funktion r gegeben für die nur der Typ ∀α.List α → List α bekannt sei aber nichts über die Implementierung der Funktion so wissen wir, daß für eine beliebige Funktion a : T → T′ die Gleichung

(map a) ∘ r_{T} = r′_{T} ∘ (map a)

gilt.

2.3 Algebraische Datentypen

Eine echte Programmiersprache mit Überladung muß verschiedene Sprachmittel anbieten, dazu gehört natürlich im Kern der λ-Kalkül desweiteren werden die algebraischen Datentypen zur Repräsentation von Daten und die Rekursion als zentrale Kontrollstruktur benötigt. Algebraische Datentypen sind bekannt aus den funktionalen Sprachen ML, Haskell, Miranda. Es gibt zwei Operationen um algebraische Datentypen im Programm zu behandeln, mit den benutzerdefinierten Konstruktoren werden Werte zusammengesetzt, mit der Musterpassung werden die Werte ausgewählt und in ihre Teile zerlegt. Wir wollen uns hier mit den Konstruktoren beschäftigen, und die algebraischen Datentypen als besonders ausdrucksstarke Signaturen betrachten. Für die Überladung sind die algebraischen Datentypen besonders bedeutsam, da Sie Typkonstruktoren definieren und somit die Typsprache anreichern welche zur Auswahl der Instanzen genutzt wird. In Beispielen wollen wir folgende Syntax für algebraische Datentypen benutzen :

data  List a =  Cons  (a, List a)      | Nil
data  Tree a =  Branch(Tree a, Tree a) | Leaf a

In dem obigen Beispiel werden zwei neue Typen definiert, gebildet aus den Typkonstruktoren List und Tree die jeweils ein Typargument akzeptieren (hier der formale Parameter a). Die Werte zu List Int sind Listen mit Integereinträgen wobei die zwei möglichen Fälle für Listen durch die Datenkonstruktoren gebildet werden. Die zwei Fälle sind, einerseits die leere Liste durch Nil repräsentiert und anderseits ein Eintrag mit Restliste durch Cons repräsentiert. In unserem Beispiel sind die Werte für Typen die mit Tree gebildet werden binäre Bäume mit Einträgen eines Typs in den Blätter, dabei werden die Verzweigungen durch den Datenkonstruktor Branch und die Blätter durch den Datenkonstruktor Leaf gebildet.

2.3.1 Begriffsdefinitionen

Hier folgen die Begriffe die zur formalen Definition der algebraischen Datentypen benötigt werden. Eine Signatur S ist ein Tupel S = (C, a) wobei C eine Menge von Konstruktoren ist und a eine Funktion a : C → ℕ_{0} ist die zu jedem Konstruktor eine Stelligkeit angibt. Sei eine Menge E gegeben. Dann benennen wir mit E^{∗} die Mengen der endlichen Sequenzen, gebildet mit den Elementen von E, wobei ϵ die leere Sequenz sei. Der Punkt “.” bedeutet die Aneinanderreihung (oder Konkatenation) der Sequenzen, geschrieben als p.q. Dabei wird die Sequenz p Präfix und die Sequenz q Suffix genannt. Desweiteren schreiben wir |p| für die Länge einer Sequenz p ∈ E^{∗}. Die Elemente der Menge ℕ^{∗}, also die Sequenzen von natürlichen Zahlen werden Pfade p genannt. Sei eine Menge Var von Variablen gegeben, dann konstruieren wir die Menge T m(S, Var) oder T m(C, Var) (wenn die Stelligkeit a klar ist), genannt die Menge der Terme über die Variablen aus Var. Ein Term t sei definiert als präfixgeschlossene partielle Abbildung von Pfaden auf Konstruktoren :

t : ℕ^{∗} → C ∪ Var
t.p =^{def} t(p)  wobei p ∈ ℕ^{∗}
t.p.q def ⟹ t.p def  (Präfixgeschlossenheit)
t.p = c ∈ C ∧ 1 ≤ i ≤ a(c) ⟹ t.p.i def (stelligkeitsabgeschlossen)

wobei t.p def ausdrückt, daß die partielle Funktion t an dem Pfad p definiert ist. Man beachte, daß bei der Definition des Terms nicht angenommen wurde, daß der Definitionbereich der partiellen Funktion endlich sei. Also schließt die Definition neben den endlich darstellbaren Termen auch nichtendliche markierte Bäume über eine gegebene Signatur und Variablenmenge ein. Diese Bäume können also auch unendliche Äste besitzen. Wir wollen nun eine Verallgemeinerung der Termkonstruktion betrachten. Sei ein Konstruktor c ∈ C der Stelligkeit n = a(c) und eine Sequenz von Termen \overline{t} der selben Länge gegeben. so kann der Konstruktor c auf die Argumente \overline{t} angewendet werden und man erhält einen neuen Term c\overline{t} durch Besetzung der leeren Stellen von c. Nun sollen ähnlich zu den Konstruktoren als Bausteine der Terme die Kerne als Bausteine der Terme erläutert werden. Wir definieren den Begriff des Kerns eines Terms als präfixabgeschlossene partielle Abbildung von Pfaden auf Konstruktoren welche die Stelligkeit respektieren. Die Menge K(S) der Kerne zu einer Signatur S enthält die folgenden Elemente :

k : ℕ^{∗} → C
k.p =^{def} k(p)  wobei p ∈ ℕ^{∗}
k.p.q def ⟹ k.p def  (Präfixgeschlossenheit)
kp.n def ⟹ 1 ≤ n ≤ a(k.p) n ∈ ℕ (stelligkeitskorrekt)

Kerne enthalten also keine Variablen. Beim Vergleich von Kernen und Termen fällt auf, daß die Terme stelligkeitsabgeschlossen sind während die Kerne nur stelligkeitskorrekt sind. Während alle Konstruktorstellen in einem Term besetzt sind, gibt es zu einem Kern also eine Menge von unbesetzten Stellen. Diese Menge sei als pl(k) = {p | k.p def ∧k.p.n undef ∧1 ≤ n ≤ a(k.p)} definiert. Die Zahl a(k) = |pl(k)| gibt die Anzahl der unbesetzten Stellen eines Kerns an, man könnte sie als Analogie zu der Stelligkeit eines Konstruktors ansehen. Nachdem die Pfade p Sequenzen von Zahlen sind können sie mit der lexikographischen Ordnung geordnet werden. Zu einer Menge von Pfaden P können wir also die Sequenz von Pfaden \overline{p} =< P > definieren welche durch die Sortierung von P nach der lexikographischen Ordnung entsteht. Sei nun ein Kern k gegeben und eine Sequenz von Termen \overline{t} der Länge a(k) so läßt sich durch Besetzung der leeren Stellen pl(k) ein neuer Term k\overline{t} bilden, indem die Stellen zu einer Sequenz von Pfaden formiert werden \overline{p} =< pl(k) > (man beachte die Längengleichheit |\overline{p}| = |\overline{t}|) werden die Stellen mit entsprechenden Termen besetzt :

k\overline{t}.p = \begin{cases}k.p & wenn k.p def \\ t_{i}.p′ & wenn ∃p′′ ∈ pl(k) mit p = p′′.p′ ∧ p′′ = p_{i} ∧ t_{i}.p′ def \\ undef & sonst \end{cases}

Wir sagen der Term t entsteht durch Besetzung der Stellen des Kerns k mit den Argumenten \overline{t}. Die umgekehrte Sichtweise ist die der Kernzerlegung. Sei ein Term t gegeben so bildet eine präfixabgeschlossene Teilmenge der Pfade in t also V ⊆ {p | t.p def ∧ t.p ∉ Var} einen Definitionsbereich für einen Kern k von t und der Term kann in einen Kern mit Stellenbesetzung zerlegt werden t = k\overline{t}.

Die folgenden technischen Begriffe werden in der vorliegenden Arbeit noch gebraucht. Wir definieren die Menge pth(t) =^{def} {p | t.p def} für eine Term t, es handelt sich also dabei um den Definitionbereich der partiellen Funktion oder die erreichbaren Punkte in einem Term. Außerdem definieren wir die Menge der Nutzungen einer Markierung in einem Term als occ(t, c) =^{def} {p | t.p = c} wobei die Markierungen Konstruktoren oder Variablen sein können c ∈ C ∪ Var. Damit definieren wir die Relation c occ t wenn die Markierung c in dem Term t auftritt d.h. für occ(t, c) ≠ ∅.

Wenn wir mit strikt auswertenden funktionalen Sprachen arbeiten, bedeuten unendliche Datenwerte eine Programmdivergenz. Also nennen wir einen Term t endlich wenn die Abschätzung |pth(t)| < ∞ gilt wobei |S| die Kardinalität einer Menge S bedeutet.

Ein Teilterm eines gegebenen Terms t an einem Pfad p ist definiert durch die Notation t|p =^{def} λq. t.p.q. Die Menge der Teilterme eines gegebenen Terms definiert durch sub(t) =^{def} {t|p | p ∈ pth(t)}. Für einen gegebenen Kern k lassen sich die Begriffe Pfadmenge pth(k), Auftreten eines Konstruktors c occ k, occ (c, k), Teilkern k|p und Subkerne sub(k) ohne Änderung übernehmen.

Die Menge der benutzten Variablen in einem Term t wird als tv(t) = sub(t) ∩ V notiert, wobei wir in der Mengengleichung Teilterme die nur an der Wurzel durch eine Variable definiert sind mit der Variable gleichgesetzt haben. Wenn Terme keine Variablen verwenden tv(t) = ∅ dann werden Sie Grundterme genannt. Also definieren wir GT m(S) als die Menge der Grundterme über eine gegebene Signatur S. Wir benutzen nun die Definitionen von Signaturen, Pfade und Terme um algebraische Datentypen als besonders ausdrucksreiche zweischichtige Signatur darzustellen. Es wird eine Schicht von Typen definiert und damit eine Schicht von Daten.

Definition. (algebraische Datentypen) Ein algebraischer Datentyp A ist ein 5-Tupel (T , a, D, arg, t). Dabei ist T die Menge der Typkonstruktoren und das Tupel (T , a) ist eine Signatur. Die zugehörige Menge der Terme T y =^{def} T m(T , Var) wird die Menge der Typen genannt. Wir definieren für jede natürliche Zahl n ∈ ℕ eine Menge V_{n} =^{def} {α_{1}, …, α_{n}} von n verschiedenen Typvariablen. Die Mengen D enthält als Elemente die Datenkonstruktoren. Die Abbildung t gibt zu jedem Datenkonstruktor eine Sorte durch die Abbildung t : D → T . Für jeden Typkonstruktor T ∈ T definieren wir die Menge der zugehörigen Datenkonstruktoren D_{T} =^{def} {D | t(D) = T }. Die Abbildung arg gibt den Typ und die Anzahl der Argumente für einen Datenkonstruktor.

arg : D → T y^{∗}  wobei  ∀D ∈ D.a(t(D)) = n ⟹ arg(D) ∈ T m(T , V_{n})^{∗}

Dabei bedeutet die Nebenbedingung, daß in den Argumenttypen eines Datenkonstruktors die Anzahl der verschieden Typvariablen V_{n} durch die Stelligkeit a(t(D)) = n des zugehörigen Typkonstruktors begrenzt ist. Wir erweitern die Anwendung von Pfaden auf Typen zu dem erweiterten Begriff auf Typsequenzen. Für die Typsequenz \overline{τ} = τ_{1} … τ_{n} ∈ T y^{∗} definieren wir den Zugriff \overline{τ}.i =^{def} τ_{i} gdw der Index in den Grenzen bleibt 1 ≤ i ≤ n also ist dann \overline{τ}.i das i-te Element der Sequenz.

Nun wollen wir an einen Beispiel sehen wie die Elemente einer Deklaration in die Signatur eines algebraischen Datentyps verteilt werden. Die Definition des Listentyps List a = Nil | Cons (a , List a) ergibt dann die Signatur A = (T , a, D, arg, t) des algebraischen Datentyps, wobei :

                 T  = {List}

a(List) = 1

                 D  = {Nil, Cons}
                 t  = {Nil ↦ List, Cons ↦ List}
                 arg  = {Nil ↦ ϵ, Cons ↦ α.Listα}

Ein Typ τ ist durch folgende Grammatik definiert τ ::= α | τ → τ | T \overline{τ} (wobei wir “→” als einen Typkonstruktor ansehen mit der Stelligkeit 2). Ein reiner Datentyp ist nur aus algebraischen Typkonstruktoren zusammengesetzt (τ ::= α | T \overline{τ}) wobei die Argumenttypen der Datenkonstruktoren keine Funktionstypen enthalten.

2.3.2 Einbettung in Programmkalküle

Bisher wurden die algebraischen Datentypen als eine erweiterte Signatur A = (T , a, D, arg, t) dargestellt. Wir wollen nun vorführen, wie der Lambdakalkül mit algebraischen Datentypen angereichert werden kann. Im Lambdakalkül sind die Konstanten c zur Erweiterung vorgesehen.

e ::= x | c | λx.e | ee′

Bei einem getypten Kalkül werden die Konstanten getypt angegeben, damit ist dann auch gleich die wohlgetypte Nutzung der Konstanten festgelegt. Zusätzlich zur Spracherweiterung wird die operationale Semantik durch δ-Regeln angereichert welche die zur Konstante gehörige Operation erläutert.

c\overline{e} ⟶^{δ} \overline{e}′

Wir definieren nun die zusätzlichen Konstanten bei Einfügung eines algebraischen Datentyp in den Lambdakalkül und die zugehörigen Operationen zu den Konstanten.

Sei eine erweiterte Signatur A = (T , a, D, arg, t) gegeben, so wollen wir folgende Benennungen vornehmen. Zu einen Datenkonstruktor D ∈ D sollen dessen Sorte t(D) = T und dessen Argumente bekannt arg(D) = \overline{τ} sein wobei die benutzten Typvariablen als Sequenz dargestellt seien \overline{α} = α_{1} … α_{n} für a(T) = n. Zuletzt sei angenommen, daß die zu T gehörigen Datenkonstruktoren numeriert seien D_{T} = {D_{1}, …, D_{m}}. Im folgenden soll nun ein getypter Kalkül mit algebraischen Datentypen erweitert werden dazu wird zunächst die Typsprache erweitert.

τ ::= α | τ → τ′ | ∀α.τ | T\overline{τ}

wobei die Stelligkeit des Typkonstruktors eingehalten werden soll a(T) = n ⟹ |\overline{τ}| = n. Es gibt zwei Arten von Konstanten zur Anreicherung des Lambdakalküls die Konstruktoren und die Destruktoren. Zu jeden Datenkonstruktor D gibt es einen Konstruktor c_{D} : ∀\overline{α}.\overline{τ} → T \overline{α} statt c_{D}\overline{e} schreiben wir kurz D\overline{e}. Zu jedem Typkonstruktor T gibt es einen Destruktor. Wir wollen die Argumenttypen der zu T gehörigen Datenkonstruktoren mit \overline{τ}_{i} = arg(D_{i}) benennen, dann hat der Destruktor den Typ:

d_{T} : ∀α.∀\overline{α}.T \overline{α} → (\overline{τ}_{1} → α) → … → (\overline{τ}_{m} → α) → α

Die Konstruktoren bauen also Werte des Typs T \overline{τ} auf während Destruktoren diese Werte zerlegen. Der neue Redex in dem Kalkül ist eine Anwendung eines Destruktors auf einen Konstruktor. Die neue Reduktionregel ist :

d_{T} (D_{i}\overline{e})\overline{f} ⟶^{δ} f_{i}\overline{e}

Aus den obigen Definitionen ist ersichtlich, daß die δ-Regel die Eigenschaft der Subjektreduktion erhält.

2.3.3 Erweiterung der Parametrizität

Wir wollen nun auch die Theorie der Parametrizität um algebraische Datentypen erweitern. So wie das System F die Grundlage der Parametrizitätstheorie war, wollen wir nun annehmen das System F sei um algebraische Datentypen erweitert wie oben beschrieben.

Zur Erweiterung der Gleichheit =_{τ} des Systems sind außer der δ-Regel keine weiteren Regeln nötig, da die Kongruenz dieser Relation auch auf Konstanten ausgedehnt ist.

⊢^{R} ∀T ∈ T .∀D_{i} ∈ D_{T} .∀α.∀\overline{α}.∀f_{1} : \overline{τ}_{1} → α … ∀f_{m} : \overline{τ}_{m} → α.∀\overline{x} : \overline{τ}_{i}. d_{T} (D_{i}\overline{x})\overline{f} =_{α} f_{i}\overline{x}

wobei wieder die Datenkonstruktoren zu T numeriert seien D_{T} = {D_{1}, …, D_{m}} und die Argumenttypen mit \overline{τ}_{i} = arg(D_{i}) benannt seien. Nun läßt sich auch der Typkonstruktor T als Relationskonstruktor erweitern. Sei eine Sequenz von definierten Relationen \overline{ρ} ⊂ \overline{τ} × \overline{τ}′ der Länge n = a(T) gegeben, dann definieren wir die neue Relation als

e T \overline{ρ} e′ ≡ ⋁_{i=1}^{m}((e =_{T \overline{τ}} D_{i}\overline{e}) ∧ (e′ =_{T \overline{τ}′} D_{i}\overline{e}′) ∧ (\overline{e}([\overline{ρ}/\overline{α}]\overline{τ}_{i})\overline{e}′))

Damit erhalten wir durch strukturelle Erweiterung wieder die Konstruktion [ρ/α]τ nun auch auf Typen mit algebraischen Datentypen.

Wir wollen nun auch noch die kategorischen Begriffsbildungen auf algebraische Datentypen erweitern. Dazu erläutern wir die Konstruktion eines Funktors (oder map-Funktion) für reine algebraische Datentypen τ. Wir definieren alle Typvariablen, die in einem reinen algebraischen Datentyp auftreten als positiv. Für die Sequenz von Typvariablen \overline{α} = α_{1} … α_{n} = tv(τ) definieren wir eine Funktion:

m_{τ} : ∀\overline{α}.∀\overline{β}.(α_{1} → β_{1}) → … → (α_{n} → β_{n}) → τ → [\overline{β}/\overline{α}]τ

Dabei ist die Definition der Funktion m_{T \overline{τ}} strukturell auf Funktionen m_{T} gestützt. Die Funktionen m_{T} haben den folgenden Typ

m_{T} : ∀\overline{α}.∀\overline{β}.(α_{1} → β_{1}) → … → (α_{n} → β_{n}) → T \overline{α} → T \overline{β}

wobei die Länge der Typvariablensequenz der Stelligkeit des Typkonstruktors entspricht also \overline{α} = α_{1} … α_{n} für a(T) = n. Sei nun \overline{β} ⊆ \overline{α} eine Teilsequenz, dann läßt sich natürlich für Argumentsequenzen \overline{f} der selben Länge |\overline{f}| = |\overline{α}| eine Inklusionsfunktion inc \overline{f} = \overline{f}′ definieren die jene Elemente aus der Sequenz \overline{f} auswählen welche der Teilsequenz \overline{β} ⊆ \overline{α} entsprechen. Wir erhalten die Typisierung inc : ∀\overline{α}.\overline{α} → \overline{β}. Im Fall eines algebraischen Datentyps haben wir für jeden Datenkonstruktor D ∈ D_{T} eine Teilmengenbeziehung tv(τ_{i}) ⊆ \overline{α} mit arg(D) = τ_{1} … τ_{l}. Also nehmen wir entsprechende Inklusionsfunktionen inc_{i} an. Die ähnliche Situation finden wir für eine Typ T τ′_{1} … τ′_{j} vor, also entsprechen Inklusionsfunktionen inc′_{i} den Teilmengenbeziehungen tv(τ′_{i}) ⊆ tv(T \overline{τ}′). Mit diesen Vorbereitungen können wir nun strukturell rekursiv die Funktoren definieren :

\begin{aligned}m_{α} & = & app (app : ∀αβ.(α → β) → α → β ≡ λf.λx.fx) \\ m_{T} \overline{f}(D\overline{e}) & = & D(m_{τ_{1}}(inc_{i}\overline{f})e_{1}) … (m_{τ_{l}}(inc_{l}\overline{f})e_{l}) \\ m_{T \overline{τ}′} \overline{f} & = & m_{T} (m_{τ′}_{1}(inc′_{1}\overline{f})) … (m_{τ′}_{j}(inc′_{j}\overline{f})) \end{aligned}

Durch eine einfache strukturelle Induktion lassen sich die Funktorgesetze m_{τ} \overline{id} = id und (m_{τ} \overline{f}) ∘ (m_{τ} \overline{g}) = m_{τ}(\overline{f} ∘ \overline{g}) zeigen. Die Definition des Funktors läßt sich auf polarisierte Typen erweitern so erhält man auch für System F mit algebraischen Datentypen die Konstruktion [f/α]τ. Nachdem nun alle Begriffe erweitert wurden ist es offensichtlich, daß sich auch die Beweise der wesentlichen Sätze auf algebraische Datentypen erweitern lassen. Wir erhalten dann eine erweiterte Theorie für System F mit algebraischen Datentypen in der die Sätze für Identitätserweiterung, für logische Relationen, für Graphen und für allgemeine Assotiativität weiterhin gültig sind.

2.3.4 Algebraische Datenwerte

Definition. (Substitution) Eine Substitution S ist eine Abbildung von Var nach T y mit der Nebenbedingung, daß die Menge dom(S) =^{def} {Sα ≠ α | α ∈ Var} endlich ist. Die Substitution kann strukturell erweitert werden, so daß Sie auf Typen und Sequenzen von Typen arbeitet. Sei ein Typkonstruktor T gegeben dann können wir aus dem Typ T \overline{τ} eine Substitution konstruieren [\overline{τ}] =^{def} α_{i} ↦ \overline{τ}.i für 1 ≤ i ≤ a(T) also gilt dom([\overline{τ}]) = V_{a(T)}.

Eine Substitution wird Grundsubstitution genannt, wenn im Bildbereich keine Typvariablen auftreten ∀α ∈ dom(S). tv(Sα) = ∅.

Mit der Definition ad =^{def} λd.|arg(d)| : D → ℕ_{0} erhalten wir eine Stelligkeitsfunktion für die Menge D der Datenkonstruktoren, so daß das Tupel (D, ad) eine Signatur bildet. Wir nennen die Menge der Terme T m(D, V) die Menge der Datenschemen. Man beachte, daß Typvariablen in den Datenschemen auftreten können; Datenschemen bilden also ein Schema welches bei Ersetzung der Typvariablen durch Grundterme zu einem Grundwert wird. Algebraische Datenschemen sind Datenschemen die getypt werden können.

Definition. (algebraische Datenschemen) Sei τ ein reiner Datentyp und die Menge der Typvariablen tv(τ) sei aufgeteilt in die Menge der gebundenen Variablen \overline{α} und die Menge der freien Variablen \overline{β}. Wir definieren die Menge der algebraischen Datenschemen durch die Abbildung schm : V × T y → T m(D, V) von einem reinen Datentyp τ (oder einer Sequenz von Typen \overline{τ}) und eine Menge von gebundener Typvariablen auf eine Menge von Datenschemen (oder eine Menge von Tupeln aus Datenschemen):

schm(∀\overline{β}.T \overline{τ}) =^{def} \{D\overline{v} | D ∈ D_{T} ∧ \overline{v} ∈ schm(∀\overline{β}.[\overline{τ}]arg(D))\}
schm(∀\overline{β}.α) =^{def} \begin{cases}∅ & gdw α ∈ \overline{β} \\ \{α\} & sonst \end{cases}

Sequenzen von Typen \overline{τ} werden auf das kartesische Produkt ihrer Komponenten abgebildet

schm(∀\overline{β}.\overline{τ}) = ∏_{i} schm(∀\overline{β}.\overline{τ}_{i})

wenn also eine Komponente die leere Menge ∅ ist, so kollabiert auch das Produkt zur leeren Menge.

Offensichtlich läßt sich die Wirkung der gebundenen Typvariablen auf die Menge der zugehörigen algebraischen Datenschemen einfach durch einen Mengenschnitt ausdrücken schm(∀\overline{β}.τ) = schm(τ) ∩ T m(D, tv(τ) \ \overline{β}).

Bisher waren in der Definition von allgemeinen Datenwerten sowohl endliche Datenwerte als auch unendliche Datenwerte enthalten. Zum Beispiel erhalten wir eine unendliche Liste von 1 Einträgen durch die folgende Definition. let ones = Cons ( 1, ones) in ... In einer bedarfsauswertenden Sprache kann mit solchen Werten gearbeitet werden. In Abschnitt 5.2 wird auf Eigenschaften von algebraischen Datenwerten eingegangen die nur für die Betrachtung von endlichen Datenwerten gelten. Wir wollen im folgenden annehmen, daß die Datenwerte endlich sind.

Nachdem wir schon algebraische Datentypen in den Lambdakalkül eingebettet haben, wollen wir nun den Begriff des Wertes aus Sicht der Kalküle definieren. Werte treten in dem Lambdakalkül als Resultate der Auswertung von Termen auf. Wir zerlegen die Grammatik der Terme, so daß ein Wert keinen Toplevelredex enthalten kann; also eine grammatikalische Beschreibung der normalisierten Terme :

\begin{aligned}v & ::= & x | λx.e | D\overline{v} | d_{T} x\overline{v} \\ e & ::= & v | ee′ | d_{T} e\overline{e} \end{aligned}

Schließlich definieren wir die Schemen welche in einer strikt auswertenden Sprache benutzt werden; eben alle endlichen Schemen da alle unendlichen Schemen eine Divergenz darstellen fschm(σ) = {v | v ∈ schm(σ) und v endlich}. Die Datenschemen entsprechen den Kernen von Termen. Bei Ersetzung der Typvariablen eines Schemas s ∈ schm(τ) durch Werte soll ein Datenwert entstehen.

Nun wollen wir die geschloßenen Werte zu einem Typ definieren als

cval(τ) = {v | S Substitution ⊢ v : ∀Sτ}

wobei der Allabschluß auf Typen als ∀τ ≡ ∀\overline{α}.τ ∧ tv(τ) = \overline{α} definiert sei. Aus einem Datenschema läßt sich ein Wert konstruieren, wenn alle Typvariablen des Schemas s ∈ fschm(τ) mit Werten besetzt werden. Wir definieren die besetzbaren Stellen eines Schemas s als alle Pfade welche zu einer Typvariable führen also pl(s) = ⋃_{α∈tv(s)} occ (s, α). Sei also ein Datenschema s ∈ fschm(τ) gegeben so wollen wir die Stellen lexikographisch sortieren zu einer Sequenz \overline{p} =< pl(s) >. Sei weiter eine Substitution S mit dom(S) ⊆ tv(τ) und einer Sequenz von Werten \overline{v} mit |\overline{v}| = |\overline{p}| gegeben, so führt die Besetzung von Stellen mit Werten zu einem neuen geschlossenen Wert ⊢ s\overline{v} : ∀Sτ wenn die Wertsequenz typkorrekt ist d.h. ∀i.1 ≤ i ≤ |\overline{v}|. ⊢ v_{i} : ∀Ss.p_{i} Wir haben jetzt durch Stellenbesetzung eines Schemas einen Wert konstruiert. Nun wollen wir umgekehrt die eindeutige Zerlegung eines geschlossenen Wertes beweisen.

Lemma 2.3.1 (Eindeutige Zerlegung von geschlossenen Datenwerten) Sei ein geschlossener Wert v ∈ cval(τ) gegeben so gibt es genau ein Datenschema s ∈ schm(τ), daß sich der Wert zu v = s\overline{v} zerlegen läßt. Beweis: Die Schemen sind für reine Datentypen definiert also hat der Typ die Struktur τ = T \overline{τ} für einen Typkonstruktor T. Nachdem v ein geschlossener Datenwert ist untersuchen wir die Fälle für die Herleitung der Aussage ⊢ v : ∀ST \overline{τ} (1) . Der Wert v kann keine Variable x sein, da die Typothese leer ist. Der Fall v = λx.e ist ausgeschlossen, da dieser Term nur einen Funktionstyp besitzen kann. Der Fall v = d_{T} x\overline{v} kann wieder wegen der leeren Typothese ausgeschlossen werden, denn dort müßte ein Eintrag für die freie Termvariable x vorhanden sein. Also bleibt nur noch der Fall v = D\overline{v} für einen Datenkonstruktor D ∈ D_{T} übrig. Nun wenden wenden wir strukturelle Induktion auf die Zerlegung der Wertesequenz \overline{v} an. Für die Argumenttypisierung arg(D) = τ′_{1} … τ′_{n} wissen wir aus der Herleitung (1) , daß wir folgende Herleitungen ⊢ v_{i} : ∀S[\overline{τ}]τ_{i} für 1 ≤ i ≤ n besitzen. Die Induktion gibt uns die Zerlegungen v_{i} = s_{1}\overline{v}_{i}. Daraus bauen wir ein Schema s = Ds_{1} … s_{n} ∈ schm(T \overline{τ}) und eine Zerlegung s\overline{v}_{1} … \overline{v}_{n} = D\overline{v} = v □.

Aus der Definition von Parametrizität und der eindeutigen Zerlegung von Werten erhalten wir nun den folgenden Satz. Für einen reinen Datentyp τ mit Typvariablen \overline{α} = tv(τ) und einer Sequenz von Relationen \overline{R} selber Länge gilt, daß zwei geschlossene Werte nur dann in Beziehung stehen wenn Sie über das selbe Schema zerlegt werden.

∀v, v′ ∈ cval(τ) v([\overline{R}/\overline{α}]τ)v′ ⊃ s\overline{v} = v ∧ s\overline{v}′ = v′ (a)

Dies ist einfach der Definition der Relation ([\overline{R}/\overline{α}]τ) zu entnehmen. Mit einfacher struktureller Induktion ist auch die Aussage herzuleiten welche nun die Argumentsequenzen \overline{v} und \overline{v}′ der Zerlegung in Beziehung setzt.

s\overline{v}([\overline{R}/\overline{α}]τ)s\overline{v}′ ≡ ∀i.1 ≤ i ≤ |\overline{v}| v_{i}([\overline{R}/\overline{α}](s.p_{i}))v′_{i} (b)

wobei wir wieder die sortierte Sequenz \overline{p} =< pl(s) > der Schemastellen verwendet haben, also ist der Ausdruck s.p_{1} = α ∈ tv(τ) = \overline{α} eine Typvariable. Damit ist der Ausdruck ([\overline{R}/\overline{α}](s.p_{i})) die Relation R_{j} aus der Sequenz \overline{R} entsprechend der Typvariable α_{j} aus der Sequenz \overline{α}.

Nun wollen wir Funktionen f : ∀τ → τ′ zwischen reinen algebraischen Datentypen charakterisieren. Ziel der Untersuchung ist ein Satz entsprechend der allgemeinen Komutativität welche wir in dem Abschnitt 2.2 über Parametrizität bewiesen haben. Dort hatten wir durch Blick auf den Typ der Funktion r : ∀α.List α → List α festgestellt, daß die Funktion r auf die Einträge der Liste keinen Einfluß nimmt, also die Einträge nur umgeordnet, kopiert oder verworfen werden können. Einen ähnlichen Satz möchten wir nun für Funktionen f : ∀τ → τ′ herleiten. Dazu bemerken wir zuerst, daß die Funktion f eine Abbildung f_{g} : cval(τ) → cval(τ′) auf geschlossenen Werten erzeugt da für einen gegebenen Wert v ∈ cval(τ) auch das Resultat w = fv ein geschlossener Wert ist. Bei Betrachtung der eindeutigen Zerlegung v = s\overline{v} und w = s′\overline{v}′ sagt der Satz nun gerade, daß die Stellenbelegung des Resultats nur aus umordenen, kopieren und verwerfen der Werte v_{i} aus der Argumentbelegung \overline{v} entstehen kann

Lemma 2.3.2 (Repräsentation von Datenfunktionen) Jede Funktion f : ∀τ → τ′ mit reinen algebraischen Datentypen τ und τ′ definiert eine Abbildung von geschlossenen Datenwerten f_{g} : cval(τ) → cval(τ′). Diese Abbildung f_{g} kann durch eine Abbildung auf Datenschemen f_{s} : schm(τ) → schm(τ′) und zu jedem Schema s ∈ schm(τ) durch eine Abbildung auf Stellen f_{p}(s) : pl(f_{s}(s)) → pl(s) dargestellt werden. Wird ein geschlossener Wert v = s\overline{v} auf f_{g}v = w = s′\overline{w} abgebildet so gilt für die Darstellung (f_{s}, f_{p}) :

f_{s}(s) = s′ und ∀p′ ∈ pl(s′). w.p′ = v.f_{p}(s)(p′)

Beweis:

Das Parametrizitätsschema für den Typ der Funktion gibt uns für \overline{α} = tv(τ → τ′) die Aussage :

∀\overline{R} ⊂ \overline{τ_{1}}×\overline{τ_{2}}.∀e : τ[t\overline{τ_{1}}/\overline{α}].∀e′ : τ[t\overline{τ_{2}}/\overline{α}]. ∀e, e′ : τ. e([\overline{R}/\overline{α}]τ)e′ ⊃ fe([\overline{R}/\overline{α}]τ′)fe′ (1)

Wenn wir nun die Argumentterme e, e′ durch geschlossene Werte v, v′ ∈ cval(τ) ersetzen und desweiteren feststellen, daß die Ergebnisse w = fv, w′ = fv′ ∈ cval(τ′) wieder geschlossene Werte sind erhalten wir die Definition von f_{g}. Für f_{g} können wir nun die Wertzerlegung betrachten. Sei für eine gegebene Relationssequenz \overline{R} die Beziehung v([\overline{R}/\overline{α}]τ)v′ (2) angenommen. Wegen (a) müssen v und v′ über das selbe Schema s_{1} zerlegen also s_{1}\overline{v} = v, s_{1}\overline{v}′ = v′. Wegen (1) sind die Resultatswerte verbunden also w([\overline{R}/\overline{α}]τ′)w′ (3) . Wegen (a) werden auch diese Werte über ein gemeinsames Schema zerlegt w = s_{2}\overline{w}, w′ = s_{2}\overline{w} damit ist die Schemenabbildung f_{s}(s_{1}) = s_{2} definiert.

Wir definieren für \overline{p} =< pl(s_{1}) > und 1 ≤ i ≤ |\overline{p}| jetzt die Relationssequenz (4) \overline{R} ≡ v_{i}R_{j}v′_{i}. Unter Nutzung von (3) und (b) erhalten wir die Beziehung w_{k}R_{j}w′_{k} gdw s_{2}.p′_{k} = α_{j} (5) für \overline{p} =< pl(s_{2}) > und 1 ≤ i ≤ |\overline{p}|. Aus der Definition (4) der Relationssequenz \overline{R} folgt wiederum, daß (5) nur erfüllt werden kann wenn es ein p_{i} mit s_{1}.p_{i} = α_{j} mit w_{k} = v_{i} gibt. Wir ändern nun eben jenes v_{i} zu einen Wert v′′, so daß dies zu einer Abänderung von v zu ṽ führt und passen die Definition der Relationssequenz \overline{R} zu \overline{R}′ entsprechend an, daß weiterhin die Argumentwerte verbunden sind ṽ([\overline{R}′/\overline{α}]τ)v′. Dann erhalten wir mit (1) für den verändeten Resultatswert w̃ = fṽ die Beziehung der Resultatswerte w̃([\overline{R}′/\overline{α}]τ′)w′ und für die Zerlegung w̃ = s_{2}\overline{w}′′ muß w′′_{k} = v′′ gelten. Damit ist die Existenz der Stellenabbildung f_{p}(s_{1}) gezeigt worden, wobei wir f_{p}(s_{1})(\overline{p}′) ↦ \overline{p} erhalten haben (unser Fall untersuchte p′_{k} ↦ p_{i} also w.p′_{k} = w′′_{k} = v′′ = ṽ.p_{i} = ṽ.f_{p}(s_{1})(p′_{k})) □

2.4 Der Hindley/Milner Ansatz

Hier soll nun das Typsystem vorgestellt werden welches die Grundlage der vorliegenden Arbeit bildet. Der Hindley/Milner-Ansatz für getyptes Programmieren mit parametrischer Polymorphie besteht aus drei Komponenten.

logisches System Das System wird im Stil der Typsysteme in Abschnitt 2.1 mit einer Typgrammatik, einer Termgrammatik und einem logischen Regelsystem präsentiert. Die Ausdrucksmächtigkeit des Systems liegt zwischen dem einfach getypten Lambdakalkül, welcher den Kern des Hindley/Milner-Systems (kurz: HM-System) bildet und dem System λ2 für implizit getypte parametrische Polymorphie, wobei die Ausdrucksmächtigkeit der der polymorphen Typen im HM-System eingeschränkt sind.

algorithmisches System Das Typisierungsproblem für das HM-System ist berechenbar. Das algorithmische System ist eine formale Präsentation des Algorithmus zur Lösung des Typisierungsproblems. Nach dem das HM-System implizit getypt ist hat man also einen Algorithmus welcher ohne Typargumente für ein Programm einen Typ berechnet, dies wird Typinferenz genannt.

semantisches Modell Das semantische Modell weist jedem Typ ein mathematisches Objekt zu (z.B. eine Menge) und weist jedem Term ein mathematisches Objekt zu (z.B. ein Element). Das Modell soll dann die Getypheitsbeziehung (in unserem Beispiel die Elementsbeziehung) und die Programmäquivalenz (z.B. Elementgleichheit) mathematisch darstellen. Insbesondere soll das semantische Modell des Hindley/Milner Ansatzes auch Typfehler benennen. Ziel der Modellierung ist die semantische Korrektheit welche besagt, daß ein wohlgetyptes Programm (im Sinne des logischen Systems) keinen Typfehler auslösen kann (im Sinne des semantischen Modells).

(LET) \frac{Γ ⊢ e : σ Γ, x : σ ⊢ e′ : τ}{Γ ⊢ let x = e in e′ : τ}  Γ ⊢ x : σ (x : σ ∈ Γ)  (TAUT)

(∀I)  \frac{Γ ⊢ e : σ (α ∉ tv(Γ))}{Γ ⊢ e : ∀α.σ}  \frac{Γ ⊢ e : ∀α.σ}{Γ ⊢ e : [τ/α]σ}  (∀E)

(→I)  \frac{Γ, x : τ ⊢ e : τ′}{Γ ⊢ λx.e : τ → τ′}  \frac{Γ ⊢ e : τ′ → τ  Γ ⊢ e′ : τ′}{Γ ⊢ e e′ : τ} (→E)

Abbildung 2.1: Das logische System von Hindley/Milner.

2.4.1 Das logische System

Jeweils die Typsprache und die Termsprache enthalten eine Neuerung gegenüber dem implizit getypten λ2 System für parametrische Polymorphie.

τ ::= α | T | τ → τ′
σ ::= τ | ∀α.σ
e ::= x | c | λx.e | ee′ | let x = e in e′

Die Sprache der Typen ist nun zweigeteilt in die Typen oder Monotypen τ und die Typschemen oder Polytypen σ. Man beachte, daß die Typschemen nicht die selbe Ausdruckskraft wie polymorphe λ2-Typen haben, denn für Typschemen sind Quantoren nur als Präfix zu einem Typ möglich. Die Sprache der Terme ist durch die let-Anweisung erweitert worden. Die operationale Semantik der let-Anweisung entspricht der einer Wertdefinition.

let x = e in e′ ⟶ [e/x]e′

Auf den ersten Blick erscheint diese Anweisung die selbe Ausdruckskraft wie ein Lambdaredex (λx.e′)e zu besitzen, welcher bereits in der Sprache vorhanden ist. In dem logischen System tritt aber das Zusammenspiel zwischen der Zweiteilung der Typsprache und der let-Anweisung zu Tage. Abstraktionen sind im HM-System nur über Monotypen erlaubt, während in der let-Anweisung der neu definierte Name x polymorph getypt sein kann. Die Regeln (T AUT), (→ I), (→ E) stellen genau den einfach getypten Lambdakalkül dar. Die Regeln (∀I), (∀E) haben genau die selbe Gestalt wie im λ2-System, wobei man beachten muß, daß die Typschemen σ nur Präfixquantoren enthalten, außerdem ist die Instantiierung in der (∀E)-Regel nur mit Typen τ zulässig. Die Regel (LET) ist die einzige Regel welche eine polymorph getypte Termvariable x : σ in die Typothese einfügt.

(T AUT)^{W}  \frac{x : ∀\overline{α}.τ ∈ Γ  \overline{β} neu}{[\overline{β}/\overline{α}], Γ ⊢^{W} x : [\overline{β}/\overline{α}]τ}

(→ I)^{W}  \frac{U, Γ.x : α ⊢^{W} e : τ  α neu}{U, Γ ⊢^{W} λx.e : Uα → τ}

(→ E)^{W}  \frac{U, Γ ⊢^{W} e : τ  U′U, Γ ⊢^{W} e′ : τ′ U′′ = mgu(U′τ, τ′ → α) α neu}{U′′U′U, Γ ⊢^{W} e e′ : U′′α}

(LET)^{W}  \frac{U, Γ′ ⊢^{W} e : τ′ gen(τ′, UΓ′) = σ U′U, Γ.x : σ ⊢^{W} e′ : τ}{U′U, Γ ⊢^{W} let x = e in e′ : τ}

Abbildung 2.2: Das algorithmische System von Hindley/Milner.

2.4.2 Das algorithmische System

Das algorithmische System wird wie das logische System als ein Regelsystem präsentiert. Dabei ist als wesentlicher Unterschied zu bemerken, daß das algorithmische System eine Abbildung (Γ, e) → (S, τ) spezifiziert. Zu einem gegebenen Tupel (Γ, e) (genannt Typproblem), bestehend aus einer Typothese Γ und einem Term e mit der Nebenbedingung, daß die freien Variablen des Terms in der Typothese getypt sein sollen (also fv(e) ⊆ dom(Γ)), soll ein Tupel (S, τ) berechnet werden, bestehend aus einer Substitution auf Typvariablen S und einem Typ τ. Solch eine Typisierungsberechnung wird als S, Γ ⊢^{W} e : τ notiert.

Zur Präsentation des algorithmischen Systems sind noch zwei zusätzliche Operationen nötig. Zum einen wird ein Unifikationsalgorithmus (z.B. der Originalalgorithmus von Robinson [Rob65]) mgu : (τ, τ) → S benötigt. Falls es eine Substitutionen S für zwei Typen τ_{1}, τ_{2} gibt, so daß Sτ_{1} = Sτ_{2} gilt, so findet der Algorithmus eine Substitution U mit Uτ_{1} = Uτ_{2} und S = R ∘ U. Diese Resultatssubstitution U mit der gegebenen Eigenschaft wird allgemeinster Unifikator genannt. Weiter benötigen wir eine Generalisierungsfunktion gen : (Γ, τ) → σ. Diese Funktion führt bei gegebener Typothese Γ und gegebenem Typ τ eine Quantifikation für jede Typvariable α ∈ tv(τ) \ tv(Γ) durch, das entspricht im logischen System einer (∀I)- Regelanwendung für jede der Typvariablen α.

Die Berechnung der Typisierung beruht auf der Idee, für neu eingeführte Typvariablen x eine Typ zu raten, eben eine neu eingeführte Typvariable α. Diese Typvariablen werden dann durch die Resultatssubstitution der Unifikation gebunden. Kern des algorithmischen Systems ist die Applikation ee′ wobei die Nebenbedingung, daß der Typ zu dem Argument e′ mit dem Argumentstyp der Funktion e übereinstimmen muß durch die Anwendung der Unifikation auf diese Typen erreicht wird.

Das logische System ist eine typorientierte Präsentation, denn für jede Typformation ist eine Einführungs- und eine Eliminationsregel gegeben. Dagegen ist das algorithmische System termorientiert präsentiert, da für jede Termformation eine Regel gegeben ist. Eine Typisierungsberechnung für das algorithmische System ⊢^{W} hat dann einen Beweisbaum, welcher der syntaktischen Struktur des typisierten Terms entspricht. In der vorliegenden Präsentation ist als Ausführungsreihenfolge der Typisierung ein Tiefendurchlauf des Beweisbaumes von links nach rechts vorgegeben. In dem Grundlagenpapier von Damas und Milner [DM82] wurden noch die zwei folgenden Sätze über den Zusammenhang des algorithmischen und des logischen Systems bewiesen.

Lemma 2.4.1 (Korrektheit der Typisierung) Für ein gegebenes Typproblem (Γ, e) folgt aus der Berechnung U, Γ ⊢^{W} e : τ die Existenz einer logischen Herleitung für die Aussage UΓ ⊢ e : τ. Der Beweis wird mit struktureller Induktion über die Berechnung U, Γ ⊢^{W} e : τ geführt.

Die Typschemen σ können in einer generischen Instanzrelation ⪯ angeordnet werden. Es gilt die Beziehung σ ⪯ σ′ genau dann wenn σ ≡ ∀\overline{α}.τ∧σ′ ≡ ∀\overline{β}.τ′∧\overline{α}∩\overline{β} = ∅ und eine Substitution S existiert mit Sτ = τ′ und dom(S) ⊆ \overline{α}, dann wird σ′ die generische Instanz von σ genannt oder σ ist ein allgemeinerer Typ als σ′. Der Vollständigkeitssatz besagt, daß der Algorithmus bei erfolgreicher Typisierung den allgemeinsten Typ berechnet hat.

Lemma 2.4.2 (Vollständigkeit der Typisierung) Sei ein Typproblem (Γ, e) gegeben, falls ein Typisierungsresultat (S, σ′) mit einer logischen Herleitung SΓ ⊢ e : σ′ existiert, so terminiert die algorithmische Typisierung U, Γ ⊢^{W} e : τ und für σ = gen(UΓ, τ) gilt σ ⪯ σ′.

2.4.3 Das semantische Modell

Ziel des semantischen Modell ist es der logischen Aussage Γ ⊢ e : τ eine semantische Aussage Γ ⊧ e : σ gegenüber zu stellen (siehe dazu auch C. Gunter [Gun94]). In Modellen lassen sich manche Argumentationen über Programmeigenschaften leichter formulieren und beweisen. Die Existenz eines Modells besagt aber auch die Widerspruchsfreiheit des logischen Systems. Ziel der Modellierung des Hindley/Milner Ansatzes war es nachzuweisen, daß ein wohlgetyptes Programm nicht fehlschlagen kann. Unter einem Fehlschlag ist eine unzulässige Operation zu verstehen z.B. die Anwendung der Funktion f : Int → Bool auf den Wert true führt zu dem Fehlschlag f(true).

Ein Modell bietet eine Interpretation der Sprachelemente, in unserem Fall sind die Sprachelemente die Typen und die Terme. So kann zum Beispiel der Typ τ als Menge ⟦τ⟧ interpretiert werden und der Term e als Mengenelement ⟦e⟧ interpretiert werden, so daß die Typisierungsbeziehung e : τ durch die Elementbeziehung ⟦e⟧ ∈ ⟦τ⟧ dargestellt wird. Der mathematische Raum in dem diese Interpretation ⟦ ⟧ entwickelt werden kann hat meist die Struktur einer CPO (complete partial order) um Divergenz und Rekursion modellieren zu können. Zur Modellierung des Hindley/Milner Ansatzes könnte man sich einen Raum der Form

V ≅ B + N + V → V + {wrong}

vorstellen. Das wäre ein Raum welcher isomorph ist (im gegebenen Raumbegriff) zu der disjunkten Vereinigung der booleschen Werte B der natürlichen Zahlen N der Abbildungen in V (hier ist der Abbildungsbegriff sorgsam zu wählen um nicht die Kardinalität in der definierenden Isomorphie zu verletzen) und eines ausgezeichnetes Elements {wrong}. Der Raum V enthält dann die möglichen Werte v eines Programms wobei auch die Divergenz und der Fehlschlag als zwei verschieden Werte enthalten sind. Zur Interpretation der Typen wird noch eine Ansammlung von Teilräumen I(V) (z.B. die Menge der Ideale) ausgezeichnet. Diese Teilräume sollen nur wohlgetypte Elemente enthalten, also soll die Nebenbedingung wrong ∉ I gelten. Die Erläuterung der Interpretation erfolgt nun in zwei Stufen erst für Typen dann für Terme. Grundsätzlich werden nur geschlossene Terme interpretiert. Es ist also nötig freie Variablen mit Werten zu belegen. Diese Belegungen werden auch Umgebungen genannt. Eine Typumgebung ι ∈ T yEnv = Var → I(V) ist eine Abbildung der Typvariablen auf die ausgewählten Teilräume I ∈ I(V). Wenn nun für die Teilräume I(V) entsprechend den Typkonstruktoren (also → und ∀) Konstruktionen auf Räume definiert sind, so läßt sich damit strukturell die Typinterpretation ⟦ ⟧ : T yp → T yEnv → I(V) definieren. Beispielweise zu einer gegebenen Typumgebung ι ∈ T yEnv

\begin{aligned}⟦α⟧ι & = & ι(α) \\ ⟦τ → τ′⟧ι & = & ⟦τ⟧ι → ⟦τ′⟧ι \end{aligned}

wobei der → Operator in geeigneter Weise die Ansammlung der Abbildungen zwischen den Teilräumen ⟦τ⟧ι und ⟦τ′⟧ι konstruieren soll damit wieder ⟦τ⟧ι → ⟦τ′⟧ι ∈ I(V) gilt. Eine Termumgebung η ∈ T mEnv = T mV ar → V ist eine Belegung der Termvariablen x, y, … mit Werten des Interpretationsbereichs V. Mit diesem Mittel läßt sich eine Terminterpretation ⟦ ⟧ : Exp → T mEnv → V konstruieren. Beispielsweise könnte eine Interpretation für gegebenen Termumgebungen η ∈ T mEnv folgende Definitionen enthalten.

\begin{aligned}⟦x⟧η & = & η(x) \\ ⟦λx.e⟧η & = & v ↦ (⟦e⟧(η|x ↦ v)) \end{aligned}

wobei (η|x ↦ v) die Abänderung der Abbildung η an der Stelle x zu dem Wert v darstellen soll. Um die semantische Typisierungsaussage zu erhalten benötigen wir noch für die verwendeten Termumgebungen η eine Kompatibilität mit einer Typothese. Wir sagen η ist eine Γ, ι Umgebung (kurz: η ⊧ Γ, ι) genau dann wenn für alle Einträge x : σ ∈ Γ die Beziehung η(x) ∈ ⟦τ⟧ι gilt. Eine semantische Typisierungsaussage Γ ⊨ e : σ ist gültig genau dann wenn für alle Typumgebungen ι und und kompatiblen Termumgebungen η ⊧ Γ, ι die Beziehung ⟦e⟧η ∈ ⟦τ⟧ι gilt. In dem Papier von Damas und Milner [DM82] wurde ein Modell vorgestellt und dazu der Satz der semantischen Korrektheit gezeigt, der besagt, daß aus einer logischen Typisierung eine semantische Typisierung folgt.

Lemma 2.4.3 (semantische Korrektheit) Sei die logische Aussage Γ ⊢ e : σ herleitbar, dann gilt die semantische Aussage Γ ⊧ e : σ

Als einfaches Korrolar folgt daraus, daß wohlgetypte Programme nicht fehlschlagen können. Formal ist die Aussage, daß aus der logischen Aussage Γ ⊢ e : σ für beliebige η ⊧ Γ, ι die Ungleichung ⟦e⟧η ≠ wrong folgt, was wiederum aus der semantischen Aussage Γ ⊧ e : σ ⇔ ⟦e⟧η ∈ ⟦σ⟧ι mit wrong ∉ ⟦σ⟧ι zu sehen ist.

2.5 Andere Ansätze

Da Programmiersprachen Arithmetik, Vergleiche und Ausgabe von Werten behandeln müssen ist bei der Realisierung einer Programmiersprache immer eine Behandlung von Überladung nötig. Die uniforme Behandlung dieser Aufgaben wurde jedoch erst in den Arbeiten von Wadler/Blott [WB89] und Kaes [Kae88] thematisiert. Von Wadler/Blott wurde der einflußreiche Ansatz der Typklassen vorgestellt welcher eine elegante Realisierung der Überladung in einer funktionalen Programmiersprache darstellt. Im folgenden werden Arbeiten vorgestellt die Einsichten und Methoden zur Behandlung von Überladung in Typsystemen anbieten.

2.5.1 Wadler/Blott: Typklassen

Die Arbeit von Wadler/Blott ist praktisch orientiert und beginnt mit der einheitlichen Behandlung der Standardüberladungsprobleme (Arithmetik , Vergleiche) in Typklassen.Die Typklassen können als Erweiterung des HM-Systems um zwei Termkonstrukte angesehen werden.

e ::= … | over x : σ in e | inst x : σ = e in e′

wobei die Typschemen σ ≡ ∀\overline{α}.C ⇒ σ′ wie in System O Überladungseinschränkungen x : τ ∈ C enthalten. Die over-Anweisung deklariert eine Typklasse mit dem Namen x. Zur Realisierung von over im HM-System wird zu jeder Klassendeklaration ein neuer Typkonstruktor T_{x} definiert welcher den Typen der Klassenelemente entspricht. Zum Beispiel für die Klassendeklaration der Gleichheit wird der Typkonstruktor Eq definiert und ein Klassenelement eq welches die überladene Gleichheitsfunktion repräsentiert.

Eq α = α → α → bool und over eq : ∀α.Eq α

Aus dieser Klassendeklaration folgt, daß jede überladene Instanz der Gleichheitsfunktion durch eine Instanz des allgemeinen Überladungstyps getypt sein muß. Mit der inst-Anweisung werden die Überladungsinstanzen definiert. Zum Beispiel die Gleichheit auf Int-Werten und auf Tupeln.

inst eq : Eq Int = eqInt in
inst eq : ∀αβ.{eq : Eq α, eq : Eq β} ⇒ Eq α × β
= λt.λt′.eq(fst t)(fst t′) ∧ eq(scnd t)(scnd t′)

Die Kernidee der Arbeit ist es die um inst und over erweiterte Sprache in die Sprache des HM-Ansatzes zu übersetzen. Dazu werden die neuen Typkonstanten T_{x} für die Klassendeklaration als ein dictionary-Datentyp aufgefaßt (z.B. EqD α = EqDict Eq α) und die Überladungseinschränkungen in C einer Instanzdeklaration inst x.∀\overline{α}.C ⇒ τ = e werden als zusätzliche dictionary Argumente aufgefaßt. Zu jeder Instanzdeklaration werden zwei Ausdrücke erzeugt. Einerseits der eigentliche Instanzausdruck welcher auf zusätzliche dictionary Argumente zugreift und zum anderen ein Ausdruck welcher zur gegebenen Instanz ein dictionary konstruiert. In unserem Beispiel wäre das

let eqP air : EqD α → EqD β → α × β → α × β → Bool
eqP air = λeqDa.λeqDb.λt.λt′.
eq eqDa(fst t)(fst t′)
∧eq eqDb(scnd t)(scnd t′)
let eqDP air : EqD α → EqD β → EqD α × β
eqDP air = λeqDa.λeqDb.EqDict(eqP air eqDa eqDb)

wobei die Klassendeklaration die überladene Funktion eq definiert indem sie auf das dictionary zugreift.

let eq = λ(EdDict e).e

Eine ähnliche Übersetzung von System O_{2} nach System F wurde mit der ⇝^{c}-Überset-zung definiert, welche die Auflösung von Überladung durchführt und dabei zusätzliche Argumente ähnlich den dictionaries erzeugt.

Die Arbeit von Wadler/Blott beschäftigt sich nach der Darstellung der Typklassen durch Beispiele auch mit der Formalisierung dieses Ansatzes. In der Arbeit wird ein logisches System für die Typisierung vorgestellt. Mit dem logischen System wird die Übersetzung einer Typisierungsherleitung in ein Programm der Hindley/Milner-Sprache dargestellt. Abschließend wird eine Begriffsdefinition für die generische Instanzbeziehung entwickelt und eine Vermutung für die prinzipielle Typeigenschaft aufgestellt. Die vorliegende Arbeit setzt also diese Ansätze fort, indem die Notwendigkeit von Deklarationen und Typannotationen aufgehoben wurden und ein Beweis der prinzipiellen Typeigenschaft für unseren Ansatz entwickelt wurde.

2.5.2 Kaes: Typsysteme mit Constraints

Der Artikel [Kae88] ist die erste systematische Behandlung von Überladung. In der Arbeit wird zuerst der Hindley-Milner-Ansatz mit Syntax, Semantik, logischem System und den klassischen Sätzen dargestellt. Darauf baut dann die Behandlung von Überladung in zwei Schritten auf. Zuerst wird die Auflösung von überladenen Funktionen und im zweiten Teil die Behandlung von Überladungsdeklarationen als Erweiterung des HM-Systems dargestellt.

Die Idee von Kaes ist es die regulären (also unendlichen) Mengen von Instanztypen zu einer überladenen Funktion endlich darzustellen. Diese endliche Darstellung, genannt Überladungsannahme, besteht aus 2 Teilen: zum einen gibt es die Überladungsschemen (z.B. $×$ → $ für + und *) und zweitens eine Menge von Instantiierungen für den Platzhalter$. Die Menge der Instantiierungen ist endlich dargestellt durch die Verwendung von Typvariablen welche mit überladenen Namen markiert sind. Anhand der endlichen Darstellung von Instanztypen wird der Begriff der validen Überladung o : τ relativ zu einer Menge von Überladungsannahmen formalisiert.

Mit diesen Begriffen wird die Wohlgetyptheit formalisiert und ein Typinferenzmechanismus angegeben. Kaes beschreibt weiter ein System für die Wohlgetyptheit mit Überladungsdeklarationen welches dem Typsystem von Haskell sehr ähnlich ist. Dazu wird die HM-Sprache mit einem Konstrukt für die Deklaration eines Überladungsschemas zu einem Namen und einem Sprachkonstrukt für die Instanzdeklarationen zu einem Namen erweitert. Die Arbeit schließt mit zwei Semantiken zur Überladung. Die erste Semantik entspricht einer Überladungsauflösung zur Übersetzungszeit und die zweite Semantik entspricht einer Überladungsauflösung zur Laufzeit.

Damit werden also bereits in der ersten Arbeit von Kaes alle wesentlichen Punkte der Überladung behandelt. Die vorliegende Arbeit erweitert diesen Ansatz in dem Schemadeklarationen und Typannotationen aus der Sprache entfernt werden. Daraus resultiert eine Erweiterung der Ausdrucksmöglichkeiten für überladene Funktionen bei vereinfachter Benutzung der Sprache. Aus heutiger Sicht ist auch offensichtlich, daß die von Kaes in der Typinferenz benutzte Generalisierung die Überladungsconstraints nicht berücksichtigt, also zu keinen korrekten Resultaten der Typinferenz führen kann.

In der späteren Arbeit von Kaes [Kae92] wird ein allgemeiner Rahmen zur Fassung von Typinferenz mit Constraints entwickelt. Dabei sind die Überladungseinschränkungen nur ein Fall der Constraints. Auch Subtypen werden von Kaes in diesem Rahmen behandelt. Die Idee der Arbeit ist es, das HM-System so zu erweitern, daß bei der Unifikation gleichzeitig die Widerspruchsfreiheit von Constraints geprüft wird. Kern der Arbeit ist die Begriffsbildung des Constraints und die Realisierung der Constraintprüfung durch Termersetzungssysteme.

Als Constraintbeispiele werden die Überladungseinschränkungen als Prädikate pEq(α) behandelt und das zweistellige Subtypprädikat τ ⊲ τ′ behandelt. Der Begriff der Constraintlösung wird wie folgt definiert. Zu jedem n-stelligen Prädikat P des Systems gibt es eine berechenbare Testfunktion P̂ : T y^{n} → Bool. Ein Constraint C ist eine Menge von Prädikaten. Eine Erfüllungssubstitution S eines Constraint C (kurz: S ⊧ C) ist eine Substitution mit ∀.P (τ_{1}, …, τ_{n}) ∈ C ⟹ P̂(Sτ_{1}, …, Sτ_{n}). Da aber meist die Menge der allgemeinsten Lösungen eines Constraints nicht endlich ist, wählt Kaes den Begriff der Vereinfachung von Constraints um die Constraintprüfung einzuführen. Eine Substitution S ist eine Vereinfachung des Constraints C wenn für alle Erfüllungen S′ ⊧ C eine Faktorisierung S′ = R ∘ S existiert. Mit Hilfe von Termersetzungssystemen definiert Kaes nun die Vereinfachung eines Constraints auf der Ebene der Prädikate. Zur Illustrierung unserer Beispielsprädikate dienen die folgenden Regeln :

Int ◁ Int → ∅  pEq(Int) → ∅
α × β ◁ α′ × β′ → α ◁ α′, β ◁ β′  pEq(α × β) → pEq(α), pEq(β)

Eine Constraintmenge wird genau dann erfüllbar genannt wenn Sie sich unter der Termersetzung auflösen läßt d.h. wenn die Reduktion C →^{∗} ∅ möglich ist. Bei der Untersuchung der Termersetzungssysteme fragt Kaes nach der Korrektheit, Vollständigkeit und Terminierung des Termersetzungsvorgangs und damit für diese Eigenschaften des Vereinfachungsvorganges von Constraints. Diese Eigenschaften werden aus den Eigenschaften der Prädikate abgeleitet. Man bemerkt an den Beispielen der Überladungsprädikate, daß für jeden Typkonstruktor eine Termersetzungsregel gegeben ist. Die Prädikate sind also durch die Regeln strukturell induktiv gegeben. Diese Art der Präsentation schlägt sich in dem Begriff der strukturellen Ähnlichkeit nieder. Zwei Typen τ und τ′ sind strukturell ähnlich τ ∼^{ss} τ′ wenn Sie das gleiche Baumskelet besitzen (Die Namen der Typkonstruktoren können verschieden sein, aber die Stelligkeit und die Länge der Zweige müssen übereinstimmen). Kaes definiert: Ein Prädikat erzwingt strukturelle Ähnlichkeit wenn das Prädikat nur für strukturell ähnliche Argumente erfüllbar ist. In dem Termersetzungssystem gilt dann die Implikation p(τ_{1}, …, τ_{n}) →^{∗} ∅ ⇒ τ_{1} ∼^{ss} … ∼^{ss} τ_{n}. Da nun die Überladung in der Programmiersprache so definiert ist, daß die Existenz einer Instanz immer durch die äußeren Typkonstruktoren (also für eine überladene Funktion o das Prädikat p_{o}(f_{1}(\overline{τ_{1}}), …, f_{n}(\overline{τ_{n}})) ) entschieden werden kann erzwingen die Überladungsprädikate die strukturelle Ähnlichkeit.

Diese Zusammenhänge werden von Kaes zum Entwurf des Constraintlösungsalgorithmus genutzt. Aus jeder Constraintmenge C läßt sich eine Äquivalenzrelation ∼^{C} auf Typvariablen extrahieren. Bei der Auflösung der Constraintmenge C werden occurence checks modulo der Äquivalenzrelation ∼^{C} durchgeführt; bei Verletzung dieses occurence checks ist frühzeitig die Inkonsistenz von C erkannt (d.h. ein Typisierungsfehler). Gleichzeitig läßt sich mit Hilfe der Äquivalenzklassen zu ∼^{C} eine Partitionierung der Constraintmenge vornehmen, so daß die einzelnen Teile getrennt gelöst werden können. Die Lösungsmethode von Kaes führt Constraints immer bis auf Grundinstanzen zurück, dem entspricht in der Überladung ein Auflösen bis zu Grundinstanzen von überladenen Funktionen. Es wird also unter Annahme einer geschlossenen Welt nach der Erfüllbarkeit der Constraints gesucht. Die Arbeit ist richtungweisend in dem Versuch einen allgemeinen Rahmen für Typinferenz zu entwickeln. Dieser Gedanke wird zur Zeit von uns weiterverfolgt.

Anhand dieser Analyse lassen sich nun sehr klar die Fortschritte der vorliegenden Arbeit benennen. Die Forderung von Kaes, daß Überladungsprädikate strukturelle Ähnlichkeit erzwingen führt zu einer Einschränkung der Überladungsinstanzen, so daß Instanzen bereits durch die ersten Typkonstruktoren festgelegt sein müssen. Diese Einschränkung wird in System O_{2} aufgehoben in dem Überladungsinstanzen nicht durch Typkonstruktoren sondern durch relevante Typkerne determiniert werden. Desweiteren müssen in unserem Inferenzmechanismus Constraints nicht bis zu Grundinstanzen aufgelöst werden, da nur diejenigen Instanzen von überladenen Funktionen geprüft werden die sich in einem Programmtext finden lassen. Das entspricht der Annahme der offenen Welt. System O_{2} geht noch einen Schritt weiter; bei der Constraintauflösung werden diejenigen Überladungsconstraints erkannt und entfernt deren Betrachtung unnötig ist d.h. die leeren Constraints.

2.5.3 Duggan/Cormack/Ophel: Überladung mit Kinds

Die Arbeit von Dugggan, Cormack und Ophel [DCO96] (kurz: DCO) sind erwähnenswert weil Sie einerseits eine Analyse der verschiedenen Ansätze zur Überladung anbietet und andererseits eine neue Methodik zur Behandlung von Überladung ausführt.

Die Arbeit beginnt mit der Darstellung des Ansatzes von Wadler/Blott (kurz: WB). Zur Behandlung von überladenen Namen gibt es also ein Überladungsschema o :_{o} ∀α.τ_{o} und eine Menge von Instanzen der Form o :_{i} ∀\overline{β}.\{o_{1} :_{c} τ_{1}, …, o_{n} :_{c} τ_{n}\} ⇒ τ dabei führen die Überladungseinschränkungen o_{i} :_{c} τ_{i} zu einer Einschränkung der Instantiierungsmöglichkeiten für die quantifizierten Typvariablen \overline{β}. Der Typ τ in der Instanzdeklaration wird von DCO Matrix genannt. In DCO wird die Ausdrucksmächtigkeit der Ansätze an Hand der syntaktischen Einschränkungen der Instanztypen untersucht. In diesem Rahmen läßt sich der Fortschritt der vorliegenden Arbeit sehr klar darstellen.

Vergleich der Ausdrucksmächtigkeit

In der Arbeit von Volpano/Smith [Vol93] (kurz: VS) wird nachgewiesen, daß in dem vorgeschlagenen Überladungssystem WB die Typisierung unentscheidbar ist. Weiter werden in VS Restriktionen eingeführt welche zu einem entscheidbaren Typsystem führen. Die Restriktionen schränken die Überladungsinstanzen ein, so daß nur Instanzen der folgenden Form zulässig sind :

o :_{i} ∀β_{1}, …, β_{n}.\{o :_{c} [β_{1}/α]τ_{o}, …, o :_{c} [β_{n}/α]τ_{o}\} ⇒ [T \overline{β}/α]τ_{o}

wobei τ_{o} der Typ des Überladungsschemas o :_{o} ∀α.τ_{o} ist. Die Matrix ist also immer eine Instanz des Schematyps unter der Substitution [T \overline{β}/α], wobei \overline{β} eine Permutation der quantifizierten Typvariablen ist. Zusätzlich wird für die Matrix gefordert, daß keine weiteren Instanzen von o zu dem Typkonstruktor existiert; dies wird die Diskriminanzeigenschaft genannt. Man beachte, daß im Ansatz von VS die Anzahl der quantifizierten Typvariablen die Anzahl der Überladungsconstraints und die Stelligkeit des Typkonstruktors übereinstimmen müssen. Zuletzt ist zu bemerken, daß nur einfache Rekursion einer überladenen Funktion o möglich ist. Mutuelle Rekursion ist ausgeschlossen da nur Überladungseinschränkungen über den selben Namen o zulässig sind. In DCO wird herausgehoben, daß die Restriktionen von VS gelockert werden können bei Erhaltung eines entscheidbaren Typsystems. Die erweiterten Überladungsinstanzen von DCO haben die Form:

o :_{i} ∀β_{1}, …, β_{n}.\{o_{1} :_{c} [β_{i}/α]τ_{o_{1}}, …, o_{m} :_{c} [β_{j}/α]τ_{o_{m}}\} ⇒ [T \overline{τ}/α]τ_{o}

wobei wieder die Gültigkeit der Diskriminanzeigenschaft gefordert wird. Offensichtlich ermöglichen die DCO-Instanzen mutuelle Rekursion mit Hilfe der Überladungseinschränkungen o_{k} :_{c} [β_{i}/α]Γ_{o_{k}} wobei τ_{o_{k}} das Überladungsschema zu dem Namen o_{k} ist. Weiter ist die Anzahl der quantifizierten Typvariablen, die Anzahl der Überladungseinschränkungen und die Stelligkeit des Typkonstruktors nicht mehr miteinander gekoppelt. Auch für die Form der Matrix sind mehr Möglichkeiten gegeben durch die Instanziierungssubstitution [T \overline{τ}/α]. Der Fortschritt das System O gegenüber DCO zeigt sich durch die Aufhebung der Überladungsschemen o : ∀.τ_{o}, wobei insbesondere die Aufhebung der Einschränkung tv(τ_{o}) ⊆ {α} zur Erweiterung der Möglichkeiten führt. Gegenüber DCO wird aber die Einschränkung eingeführt, daß nur Funktionstypen für die Überladungsinstanzen und Überladungseinschränkungen erlaubt sind. Die allgemeine Form von Überladungsinstanzen in System O ist :

\begin{aligned}o :_{i} & ∀β_{1}.\{o_{1}^{1} : β_{1} → τ_{1}^{1}, …, o_{n_{1}}^{1} : β_{1} → τ_{n_{1}}^{1}\} ⇒ \\ & … ∀β_{m}.\{o_{1}^{m} : β_{m} → τ_{1}^{m}, …, o_{n_{m}}^{m} : β_{m} → τ_{n_{m}}^{m}\} ⇒ T \overline{τ} → τ \end{aligned}

wobei die Diskriminanzeigenschaft gefordert wird und für die Überladungseinschränkungen die Variablenbedingung tv(τ_{j}^{i}) ⊆ {β_{1}, …, β_{i}} gelten muß.

In System O_{2} wird zusätzlich zu der Aufhebung der Überladungsschemas noch der Grundsatz der Diskriminanzeigenschaft syntaktisch aufgeweicht bis er in neuem Gewand eine semantische Bedeutung erhält. Die Diskriminanzeigenschaft wurde benötigt damit eine überladenen Funktion wohldefiniert ist. In Abschnitt 5.2 wird gezeigt, daß die Wohldefiniertheit mit der syntaktischen Erweiterung auf Diskriminanz auf relevante Typkerne übereinstimmt. Mit einem zusätzlichen Algorithmus in der Typinferenz läßt sich die Diskriminanz noch auf curried überladenen Funktionen erweitern. Damit ist zum ersten Mal die natürliche Programmiermethodik von curried Funktionen mit der Typinferenz von Überladungspolymorphie verbunden worden.

Der Ansatz: Überladung mit Kinds

Die Idee von DCO ist es die Menge der Instanzen eines überladenen Namens o nicht durch Einschränkungen zu Charakterisieren sondern durch eine reguläre Grammatik anzugeben. Die reguläre Grammatik zu einer Instanzmenge ist durch Kinds der Form :

ρ ::= κ | ⊥ | ⊤ | T \overline{ρ} | ρ ⊔ ρ′ | μκ.ρ

gegeben. Dabei entspricht ⊥ der leeren Instanzmenge und und ⊤ der Menge aller Typen. Die Instanzmenge T \overline{ρ} entspricht allen Typen T \overline{τ} wobei \overline{τ} Instanztupel der Menge \overline{ρ} sind. Der Ausdruck ρ ⊔ ρ′ entspricht der Vereinigung der Instanzmengen zu ρ und ρ′. mit der Kindvariable κ und dem Ausdruck μκ.ρ lassen sich rekursiv Mengen von Instanzen beschreiben.

Ein Beispiel soll den Zusammenhang zwischen der Überladung im Sinne von WB und der Überladungsdarstellung mit Kinds verdeutlichen. Sei die Multiplikation als Schema ∗ :_{o} ∀α.α → α → α mit Instanzen für die Typen Int und Real gegeben. Wenn nun weiter eine Multiplikationsinstanz auf Matrizen definiert sei wobei die Addition und Multiplikation auf den Matrixeinträngen benutzt wurde so erhalten wir folgende Instanzdeklaration :

∗ :_{i} ∀α.{+ :_{c} α → α → α, ∗ :_{c} α → α → α} ⇒ Matrix α → Matrix α → Matrix α

Seien für die Addition Instanzen zu Real, Cmplx und Matrix gegeben so erhalten wir die folgende Zusammenfassung des Typ für die Multiplikation

∗ : ∀α : {Int ⊔ Real ⊔ Matrix (μκ.Real ⊔ (Matrix κ))}.α → α → α

In DCO wird nun die Überladung an Hand der Kinds behandelt. Dazu werden analog zu den Einschränkungen auf die Überladungsinstanzen in WB Forderungen an die Kinds gestellt. Es sind nur gute Kinds zulässig welche die Eigenschaft der Kontraktivität und Diskriminanz erfüllen. Mit diesen Kinds wird ein logisches Typsystem ⊢_{DCO} angegeben. Weiter werden Algorithmen angegeben um leere Kinds festzustellen, um den Schnitt von Kinds zu berechnen und um die Subkindbeziehung festzustellen. Diese Algorithmen sind inspiriert durch Amadio/Cardellis Ansatz zur Subtypberechnung von rekursiven Typen [AC93]. Mit Hilfe der Algorithmen auf Kinds wird eine Typinferenz zu dem logischen System ⊢_{DCO} entwickelt wobei die Unifikation zur kinded Unifikation erweitert wird und die Korrektheit und Vollständigkeit bewiesen wird.

In Abschnitt 5 von DCO wird nun der Zusammenhang des logischen Systems ⊢_{DCO} auf Basis von kinded Überladung und der Ansatz von Wadler/Blott mit dem logischen System ⊢_{W B} auf Basis von Überladungseinschränkungen untersucht. Dabei ist anzumerken, daß eine Version des WB-Systems zu Grunde gelegt wird in der Überladungseinschränkungen immer erfüllbar sind. Für die Untersuchung wird eine Metalogik mit Hornklauseln über Subkindprädikate τ ≤ ρ und ein Herleitungssystem für die Folgerungsaussage ⊩ vorgestellt. Im ersten Schritt wird eine Übersetzung von ⊢_{W B}-Typisierungsaussagen nach ⊩-Folgerungsaussagen vorgeführt und deren Korrektheit und Vollständigkeit gezeigt. Die entsprechende Übersetzung von ⊢_{DCO} nach ⊩ und deren Korrektheit und Vollständigkeit führen zu dem Korrolar, daß ⊢_{DCO} korrekt und vollständig ist relativ zu ⊢_{W B}.

2.5.4 Nipkow, Prehofer, Snelting: Typinferenz mit ordnungssortierter Unifikation

In der Reihe von Artikeln [NS91, NP93a, NP93b] stellen Nipkow, Prehofer und Snelting einen eigenen Ansatz zur Typinferenz von Überladung vor. Das Überladungssystem entspricht den Typklassen von Wadler/Blott erweitert um eine Klassenhierarchie ähnlich der Objekorientierung. Der Typinferenzalgorithmus wird durch eine Erweiterung der Unifikation zur sortenerhaldender Unifikation gewonnen.

Die Sprache

In Erweiterung zu dem WB-Ansatz wird bei Nipkow et al eine Ordnung auf den Typklassennamen angenommen die der Unterklassenhierarchie in der Objektorientierung entspricht. Die zwei Konstrukte zur Definition von Überladungsschemas und Überladungsinstanzen haben folgende Form :

class C ≤ S where o_{c} : σ
inst T (\overline{S})C where o_{c} = e

wobei C für eine Klassennamen steht und S eine Menge von Klassennamen {C_{1}, …, C_{n}} ist, die Sorte genannt wird. Die Aussage, daß zu einem Typ τ Instanzen der Klassen S = {C_{1}, …, C_{n}} existieren wird dann kurz als Sortierung τ : S notiert.

Die Klassendeklaration besteht aus der Festlegung, daß die Klasse C eine Unterklasse aller Klassen S = {C_{1}, …, C_{n}} ist und aus der Vereinbarung eines überladenen Klassenelements o_{C} : σ zu dieser Klasse C. Damit ist eine Ordnung C ≤ C′ auf Klassen definiert die auf Sorten S ≤ S und auf Sortensequenzen \overline{S} ≤ \overline{S}′ erweitert wird. Diese Ordnung wird benötigt um die Instanzdefinition zu verstehen. Eine Instanzdefinition legt ein Element o_{C} = e der Klasse C zu dem Typkonstruktor T fest, wobei für Instanzen zu dem Typ T \overline{τ} gefordert wird, daß die Sortierung \overline{τ} : \overline{S} gilt. Zusätzlich zu der Diskriminanzeigenschaft wird für die Instanzdeklaration noch gefordert, daß die Klassenhierarchie eingehalten wird d.h. falls die Subklassenbeziehung C ≤ C′ gilt muß eine Instanzdefinition inst T (\overline{S′})C′ where o_{c} = e′ existiert mit der Abschätzung \overline{S} ≤ \overline{S}′. Diese Hierarchieerhaltung ist wesentlich für das Funktionieren des folgenden Unifikationsalgorithmus.

Unifikation mit geordneter Sortierung

Seien die Sortierung der Typkonstruktoren T (\overline{S})C und der Typvariablen α : S in einer Sortierungshypothese B gesammelt, dann kann der Begriff der sortenerhaltenden Substitution bezüglich B definiert werden. Damit läßt sich die Allgemeinheitsrelation auf Substitutionen und das Unifikationsproblem bezüglich B definieren.

Falls zu jedem Unifikationsproblem bezüglich B entweder ein allgemeinster Unifikator oder keine Lösung existiert so wird die Sortenhypothese unitär genannt. Falls weiter zu jedem Typkonstruktor T und einer Klasse C in einer Sortenhypothese eine allgemeinste Sorte \overline{S} existiert, so daß die Sortierung T (\overline{S})C gilt wird die Typhypothese B coregulär genannt. Mit diesem Begriffshintergrund wird der Unifikationsalgorithmus von Robinson erweitert, so daß das Unifikationsproblem bezüglich einer Sortierungshypothese B behandelt wird. Es wird gezeigt, daß der Algorithmus den allgemeinsten Unifikator berechnet wenn B coregulär ist also, daß das Unifikationsproblem bezüglich B unitär ist wenn B coregulär ist.

Der Typinferenzalgorithmus ist in zwei Phasen geteilt. In der ersten Phase werden die Überladungsschemen und die Überladungsinstanzen gesammelt um eine Sortierungshypothese B aufzubauen. Falls die Überladungsinstanzen die Klassenhierarchie einhalten so ist B coregulär also ist dann der Unifikationsalgorithmus nutzbar. In der zweiten Phase wird gemäß der HM-Typinferenz das restliche Programm getypt wobei die sortenerhaltende Unifikation bezüglich B genutzt wird. Die Arbeit schließt mit dem Beweis der Korrektheit und Vollständigkeit der Typinferenz bezüglich des logischen Systems.

Die Klarheit der Präsentation ist der wesentliche Fortschritt dieser Arbeit, die Abiguitätsproblematik, eine Semantik und eine Übersetzung werden nicht behandelt. Das System ist klar in den Teil zur Sortierung von Typen (τ : S) und zur Typisierung von Termen (e : τ) gegliedert. Die Unifikation ist zweigeteilt in die Unifikation von Typen und die Auflösung von Sortierungsconstraints. Diese Aufteilung des Typsystems und der Unifikation ist richtungweisend für die Entwicklung eines allgemeinen Rahmen der verschiedenen Typsysteme.

2.5.5 Mark Jones: Erweiterung von Typklassen

Die Arbeiten von Mark Jones beschäftigen sich mit der Weiterentwicklung der Typklassen. In dem Buch “Qualified Types” [Jon92] werden die Typklassen in einen allgemeinen Rahmen eingebettet, so daß die Implementierung und der Kohärenzsatz in allgemeiner Form dargestellt werden kann. Die Arbeit [JP93] beschäftigt sich mit der effizienten Implementierung der Typinferenz und der Dictionaryübersetzung für Typklassen. Mit den Konstruktorklassen aus [Jon93] wird eine Erweiterung der Typklassen vorgeschlagen und deren Nutzen am Beispiel von Funktoren, Monaden und Zustandsmonaden vorgeführt.

Qualifizierte Typen

In dem Buch [Jon92] zur Doktorarbeit von Mark Jones wird ein Ansatz entworfen dessen Ausdrucksmöglichkeiten dem System von Kaes entspricht. Dazu wird die Typstruktur mit Prädikaten erweitert wobei für die Prädikate nur wenige Axiome gefordert werden. Als Beispiele dieser Prädikate dienen Typklassen, Subtypbeziehungen und Aussagen über Records. Mit dieser Erweiterung der Typstruktur wird wie in Kaes und der vorliegenden Arbeit das logisches System ausgebaut, eine neuer Typinstanzbegriff geprägt und ein Typinferenzalgorithmus definiert.

In einem zweiten Schritt geht Jones auf Übersetzung der Sprache mit qualifizierten Typen über. In Analogie zu der Curry-Howard-Korrespondenz, die jeder Typformation eine Termformation zuordnet, ordnet Jones jeder Prädikatherleitung einen Evidenzterm zu. Für Typklassenprädikate entsprechen die Evidenzterme den dictionaries, während zu den Subtypbeziehungen Typanpassungen (coercions) korrespondieren. Weiter werden Evidenzen benutzt um aus einer Herleitung mit qualifizierten Typen ein Programm mit Nutzung der Evidenzterme zu konstruieren. Im Fall der Typklassen entspricht diese Konstruktion der Dictionaryübersetzung. Diese Übersetzung ist also eine Implementierung eines qualifiziert getypten Terms.

Nun gibt es mehrere Typherleitungen zu einem getypten Term. Die Semantik eines Terms (in diesem Fall seine Implementation) soll jedoch eindeutig sein. Für diesem Zusammenhang beweist Jones die Kohärenzaussage die besagt, daß die Evidenzübersetzung für einen getypten Term immer zu Resultaten führt die sich gleich verhalten. Zum Beweis dieser Aussage formalisiert Jones die Gleichheit mit Hilfe der operationalen Semantik von Termen mit Evidenzen und zeigt das Resultat nur für Terme deren Typen frei von Mehrdeutigkeit sind (unambigous type schemes).

Konstruktorklassen

Aus Sicht eines Softwareingeneurs ist die Überladung notwendig wenn in einem Programm verschieden codierte Instanzen für eine Idee eines Algorithmus genutzt werden. In diesem Fall hilft es zur Strukturierung des Programms wenn diesen Ideen ein Name gegeben wird und die verschiedenen Instanzen des Algorithmus an Hand der verwendeten Datenstrukturen zu unterscheiden. Nun stellt sich die Frage nach den Beispielen einer Idee mit vielen Instanzen. Hier setzt die Arbeit [Jon93] von Jones an. Es wird die Idee des Algorithmus map aus dem funktionalen Programmieren für verschiedene Datentypen (z.B. List , Tree oder Maybe ) dargestellt. Diese Typen sind Beispiele für Containertypen wobei map eine Funktion auf allen Elementen des Argumentcontainers anwendet und eine Container der Resultate erzeugt. Bei Betrachtung der verschiedenen Instanztypen für map fällt auf, daß alle Typen die Form (a -> b) -> (f a -> f b) besitzen wobei f ein Typkonstruktor ist (z.B. List , Tree oder Maybe ). Ein Typkonstruktor ist ein Beispiel für eine Typvariable welche eine Struktur besitzt die sich als Kind ∗ → ∗ (sh. Abschnitt 2.1.5) beschreiben läßt. Jones Idee ist es kinded Typvariablen bei der Typklassendefinition zu erlauben. Die Typinferenz für die Behandlung dieses Sprachmittels wird durch die Erweiterung der bekannten Unifikation realisiert. Diese Unifikation heißt kinded Unifikation und achtet bei der Bindung auf die Übereinstimmung der Kinds von Variable und Term. Jones führt den Nutzen dieses Sprachkonstrukts an vielen Beispielen vor. Die Funktion map wird als Methode der Typklasse Functor definiert wobei folgender Schematyp angegeben wird :

        map :: ∀ f:*->* ∀ a:* ∀ b:* (a -> b) -> (f a -> f b)

Weiter werden Monaden, Monaden mit Null und Zustandsmonaden mit Hilfe der Konstruktorklassen vorgeführt.

Die Klarheit der Konzepte in Jones Beispielen ist kein Zufall sondern zurückzuführen auf die unterliegenden kategoriellen Zusammenhänge. Aus diesem Blickwinker hat sich ein Strang an Forschungsergebnissen entwickelt welcher das Programmieren mit Typkonstuktoren als polytypisches Programmieren bezeichnet [MFP91, MH95, JJ96]. Kern dieses Ansatzes ist die Beobachtung, daß sich Typen als Funktoren auffassen lassen weil bereits die Sprachmittel zur Deklaration eines Typkonstruktors Funktoren sind. Die Sprachmittel zur Deklaration von Typen werden benannt (z.B als Produkt, Coprodukt, Konstante …) und als Muster einer Fallunterscheidung auf Ebene von Typkonstuktoren genutzt. Damit ergeben sich die Beispiele aus Jones Arbeit als die Instanzen eines generellen Programmschemas das polytypische Funktion genannt wird.

Zur Behandlung von struktureller Rekursion wurden kategorielle Sätze aus den Arbeiten von Freyd zu algebraisch abgeschlossenen Kategorien [Fre90, Fre92] angewendet. Dies ist also ein Beispiel in dem direkt Methoden aus der Kategorientheorie zur Entwicklung von Programmiersprachen angewendet wurden. Zusätzlich zur Programmiersprache erhält man noch eine Reihe von Transformationsgesetzen im Sinne der Parametrizität (sh. Abschnitt 2.2). In dieser Strömung wird deshalb von dem Kalkül der Programme oder dem Prinzip des algebraischen Programmieren gesprochen.

Aus Sicht der Überladungspolymorphie stellt sich die Frage ob die Idee der überladenen Funktion identisch mit der polytypischen Funktion ist. Zur Rechtfertigung der Eigenständigkeit des Überladungsbegriffs wären Beispiel von Algorithmenideen nötig die aus Ingeneurssicht überladen implementiert werden sollten aber nicht als polytypische Funktionen realisierbar sind.

2.5.6 Parametrische Typklassen

In den Arbeiten [Che94, CHO92, CO92, COH91] stellen Chen, Odersky und Hudak (kurz: COH) einen Ansatz vor um die Ausdruckskraft der Typklassen gegenüber dem WB-Ansatz zu steigern und für eine bessere Behandlung des Mehrdeutigkeitsproblems. Die Arbeit an den parametrischen Typklassen hat zu dem Ansatz von System O geführt und die Beweise für die Terminierung, Korrektheit und Vollständigkeit sind durch die Beweise für parametrische Typklassen inspiriert.

Die Grenzen der Typklassen zeigen sich am Programmierbeispiel der Sequenzen. Auf Sequenzen sei das Einfügen eines Elements und die Berechnung der Länge definiert. Listen oder Vektoren bilden Beispiele von Sequenzen. In den Typklassen von WB ist es nicht möglich Sequenzen als eine Klasse zu organisieren da zwei Typvariablen benötigt werden die Typvariable s zur Benennung der Sequenzen und die Typvariable a zur Benennung der Elemente einer Sequenz. In der Arbeit von COH wird s zum Argument der Klasse und a zum Parameter der Klasse, so daß sich folgende Codierung ergibt :

class     s : Sequence a         where
   insert : a -> s -> s
   length : s -> Int
instance  List a   : Sequence a  where
   insert = (::)
   length = (#)
instance  Vector a : Sequence a  where
   insert = VecCons
   length = VecLegth

Formal läßt sich die Erweiterung von Klassen durch Parameter sehr einfach im Vergleich zu den sortierten Typen von Nipkow et al darstellen. Ähnlich zu den Klassen C den Sorten S = {C_{1}, …, C_{n}} und den sortierten Typvariablen α : S bei Nipkow gibt es in COH Klassen mit Parametern c\overline{τ} und Klassenmengen M = \{c_{1}\overline{τ}_{1}, …, c_{n}\overline{τ}_{n}\} eingeschränkte Typvariablen α : M und Kontexte C = {α_{1} : M_{1}, …, α_{n} : M_{n}}. Damit die Kontexte einen Sinn ergeben werden durch Variablenbedingungen die geschlossenen zyklenfreien Kontexte als die wohlgeformten Kontexte ausgesucht. Auf Typebene entsprechen diese Bedingungen der Eigenschaft, daß durch Parameter in einer Instanzdeklaration keine keine unbeschränkten Typvariablen eingeführt werden können und, daß Abhängigkeitszyklen zwischen beschränkten Typvariablen und den Typvariablen in Parametern ausgeschlossen sind.

Nun läßt sich die Ausdrucksmächtigkeit der parametrischen Typklassen in Vergleich mit den DCO-Beispielen stellen. Die zulässigen Instanzdefinitionen müssen zwei Bedingungen erfüllen.

1. Es ist keine Instanz der Form inst C ⇒ α : c\overline{τ} zulässig. Das heißt das Argument einer Klasse (hier α) muß ein konkreter Typ sein.

2. Zu jedem Tupel (c, T) aus einem Klassennamen c und einem Typkonstruktor T gibt es höchstens eine Instanz der Form inst C ⇒ T \overline{τ} : c\overline{τ}′. Zur Terminierung der Typinferenz wird weiter gefordert, daß die Typsequenz \overline{τ} entweder eine Reihe von verschiedenen Typvariablen oder eine Typkonstante ist und die freien Variablen in \overline{τ}′ und C müssen in fv(\overline{τ}) enthalten sein.

Die zweite Forderung ist eine verschärfte Diskriminanzforderung die zur Terminierung notwendig ist. Die Erfüllung dieser Forderungen führt auch zu wohlgeformten Kontexten.

In COH wird die Folgerungsbeziehung C ⊩ τ : c\overline{τ} für Instanzen definiert und und eine eingeschränkte Substitution (S, C) definiert wobei S eine Substitution auf Typvariablen ist und C ein Kontext ist. Mit diesen Begriffen wird ein logisches Typsystem eine erweiterte Unifikation und die Typinferenz entworfen. Für die Typinferenz wird Terminierung, Korrektheit und Vollständigkeit relativ zum logischen System bewiesen.

Bei der Analyse des Mehrdeutigkeitsproblems für Überladung werden syntaktische Kriterien für die Möglichkeit von Mehrdeutigkeit angegeben und eine Methode zur Vermeidung von Mehrdeutigkeit mit parametrischen Typklassen angegeben. Eine Mehrdeutigkeitssituation für ein Programm mit Typklassen ergibt sich immer dann, wenn die dictionaries für das Programm bei der Übersetzung nicht eindeutig festgelegt werden können. Die Möglichkeit dieser Situation läßt sich an dem Typ σ ≡ ∀α_{i} : M_{i} ⇒ τ von Programmtermen ablesen. Ein Typ wird in COH schwach mehrdeutig genannt, wenn eine Typvariable in σ eingeschränkt wird (d.h. ein dictionary Parameter existiert) die aber nicht durch die Matrix festgelegt wird (d.h. durch die Instantiierung kann nicht auf eine Auswahl des dictionary Parameters geschlossen werden). Zum Beispiel ist der Term e : ∀αβ.\{β : c\overline{τ}\} ⇒ List α schwach mehrdeutig weil die Typvariable β eingeschränkt ist aber nicht bei Instantiierung der Matrix List α festgelegt wird.

Ein Beispiel soll nun erläutern, daß es auch mit Termen die obiges Kriterium erfüllen zu Mehrdeutigkeiten kommen kann. Die map-Funktion auf Sequenzen läßt sich folgendermaßen typisieren

 map : ( sa : Sequence a, sb : Sequence b) => (a -> b) -> (sa -> sb)

Nun läßt sich nicht spezifizieren, daß die Sequenzen sa und sb von der selben Art sein sollen. Also ist eine Funktion die Listensequenzen auf Vektorsequenzen abbildet mit eingeschlossen. Dies führt in dem Term

                          (map f) o (map g)

zu Mehrdeutigkeit. Die Sequenz des Resultats von (map g) oder äquivalent die Sequenz des Arguments von (map f) kann nicht festgelegt werden. Als Lösung wird eine Relation a ∼ b von Typen vorgeschlagen, so daß nur Typen des selben ersten Typkonstruktors in Relation stehen. Damit erhielte die map-Funktion den Typ :

  map . ( sa : Sequence a, sb : Sequence b, sa ∼ sb) => (a -> b) ->
                             (sa -> sb)

und das Mehrdeutigkeitsproblem für diesen Fall ist gelöst.

Mit parametrischen Typklassen läßt die Relation durch eine weitere Typklasse zur Extraktion von Typkonstruktoren darstellen. Man erhält erstmals eine Auflösung der Mehrdeutigkeit ohne Nutzung von höherwertiger Unifikation die bisher als notwendig befunden wurde.

2.5.7 Andere Ansätze

Alle bisher betrachteten Systeme implementieren einen Ansatz der offenen Welt, wobei sogar leere Klassen ohne Instanzen als legal angesehen werden. Dazu wären noch die Arbeiten von über Typinferenz, Augustsson [Aug93] über Typinferenz für Typklassen und Hall, Hammond, Peyton Jones und Wadler [HHPW94, HHJW96] zur formalen Definition von Typklassen in Haskell zu erwähnen. Der Ansatz der offenen Welt funktioniert sehr gut in einem System mit getrennter Übersetzung, wo der Übersetzer nicht vollständiges Wissen über alle Instanzdeklarationen hat. Den gegensätzlichen Blickwinkel dazu bildet der Ansatz der geschlossenen Welt z.B [Rou90, Smi91, Kae92] schließen leere Typschemen aus. Duggan und Ophel [DO94] untersuchen beide Ansätze durch eine Unterscheidung von offenen und geschlossenen Typarten (Kinds). Volpano [Vol93] argumentiert, daß alle bisherigen Systeme der offenen Welt die Korrektheit verletzen. Volpano erhält seine Resultate weil er in einer ungetypten dynamischen Semantik für Programme mit Typklassen arbeitet. In dieser Arbeit argumentieren wir daß diese Kritik nicht zulässig ist auf haskellartigen Programmen. Außerdem wird durch unseren Beweis der semantischen Korrektheit für eine ungetypte dynamische Semantik von System O gezeigt, daß Volpano’s Kritik nicht generell für Systeme der offenen Welt gilt.

52 KAPITEL 2. HINTERGRUND

Logisches System

3.1 Motivation

Wir beginnen mit einer Betrachtung der Designentscheidungen die beim Entwurf eine Programmiersprache mit Überladung zu treffen sind. Die Betrachtung führt zu einer Rechtfertigung der Entwurfsentscheidungen für System O. Eine anschließende Betrachtung in Kapitel 5 von kritischen Beispielen weist den Weg zum Kern des erweiterten System O_{2} ; dem Begriff der Parametrizität.

Die Bedeutung der Überladung in Programmiersprachen ist es, einen einzigen Namen o für mehrere Implementierungen zu vergeben. Wir nennen diese verschiedenen Implementierungen Instanzen des überladenen Programmelements o. Der Nutzen dieses Sprachmittels ist aus Sicht des Ingenieurs die Möglichkeit, eine Idee mit einem Namen zu benennen ohne Beachtung verschiedener Realisierungen der Idee. Die Benutzung eines Namens in einer funktionalen Programmiersprache ist immer das Auftreten in Funktionsanwendung. Also kann o in einem Programm entweder in Form ...oe... oder in Form ...eo... genutzt werden, wobei e ein beliebiger Term ist. Während der Auswertung dieses Programms kommt der Zeitpunkt, in dem diese Funktionsanwendung als aktueller Redex gewählt wird und ein Funktionsaufruf ausgeführt werden muß. Spätestens zu diesem Zeitpunkt muß eine konkrete Instanz für das überladene Programmelement o ausgewählt werden um die Berechnung durchzuführen. Nach einem Blick auf die Möglichkeiten des Auftretens in einem Programm bieten sich zwei Vorgehensweisen zur Auswahl der Instanz an.

aktive Wahl Wenn o wie eine Funktion benutzt wird ...oe..., dann wählen wir diejenige Instanz welche mit dem angebotenen Argument arbeiten kann.

passive Wahl Wenn o als Argument benutzt wird ...eo..., dann wählen wir diejenige Instanz, welche einen Wert der gewünschten Art anbietet.

Durch diese Beobachtung erhalten wir zwei Einsichten. Als erstes muß die gesuchte Instanz existieren und eindeutig sein, ansonsten würde bei fehlender Instanz ein Programmfehler ausgelöst während bei mehreren Instanzen die Wohldefiniertheit des Programms verletzt wäre. Als zweites benötigen wir einen formalen Begriff um die Erwartung, welche eine Funktion an ihre Argumente hat festzulegen; es handelt sich um den Begriff der Typen. Damit haben wir den Raum der möglichen Entscheidungen, welche getroffen werden müssen um eine Programmiersprache mit Überladung zu entwickeln. Wir müssen eine getypte Programmiersprache wählen und in diese das Sprachmittel Überladung einbetten. Als nächstes müssen wir entscheiden ob wir die Instanzauswahl für ein überladenes Programmobjekt zur Übersetzungszeit oder zur Laufzeit ausführen wollen. Zuletzt müssen wir entscheiden ob der Programmierer Typen in sein Programm schreiben soll oder ob das unnötig ist. Unsere Entscheidung war es, als getypte Programmiersprache den Kern der Sprache ML mit der parametrischen Polymorphie zu nehmen. Diese Sprache hat die Eigenschaft die Typisierung zur Übersetzungszeit vorzunehmen ohne der Notwendigkeit für den Benutzer Typen in sein Programm zu schreiben. Unser Ziel war es diese Eigenschaften auf eine Sprache mit Überladung zu erweitern. Damit die Sprache praktisch nutzbar ist müssen folgende Sprachmittel vorhanden sein :

Funktionen wie Datenobjekte Vom Blickwinkel der Programmkalküle benutzen wir den λ-Kalkül. Aus dem Blickwinken der Programmiersprachen benutzen wir eine funktionale Programmiersprache.

Parametrische Polymorphie Dieses Typsystem bietet bereits Möglichkeit Programme so zu schreiben, daß die Bedeutung von manchen verwendeten Programmelementen nicht festgelegt werden muß. Wenn Programmelemente nur beim Kopieren oder Transfer benutzt werden muß ihr Typ in dem Programm nicht festgelegt werden sondern kann offen bleiben bis zu dem Punkt an dem das Programm benutzt wird. Bei der Benutzung können dann die offenen Typen nach den Anforderungen festgelegt werden.

algebraische Datentypen Dieses Sprachmittel von ML reichert die Typsprache durch neue Typkonstruktoren an. Diese angereicherte Typsprache führt zu angereicherten Ausdrucksmöglichkeiten für Überladung wie in der Definition des Kalkül F_{o} zu sehen sein wird.

Typinferenz Der Autor von Programmen kann sich auf die Algorithmen konzentrieren und wird durch den Typisierungsmechanismus des Übersetzers und die Korrektheitseigenschaft des Typsystems unterstützt. Der Typisierungsmechanismus führt die Typisierung des Programms ohne Unterstützung des Programmierers durch. Die Korrektheitseigenschaft sichert dem Programmierer zu, daß eine bestimmte Klasse von Laufzeitfehlern von dem Programm nicht ausgelöst werden können wenn es wohltypisiert ist.

Rekursion Es gibt eine Lücke zwischen dem Bedürfnis eines Programmierers die volle Ausdruckfähigkeit zu haben um alle berechenbaren Algorithmen formulieren zu können und dem Wunsch ein korrektes Typsystem zu haben. Das heißt der Programmierer möchte die volle Rekursion benutzen. In der Arbeit [Hen93] wurde aber gezeigt, daß die Typisierung der polymorphen Rekursion nicht entscheidbar ist. In der Praxis wurde dem Problem mit monomorpher Rekursion, beholfen woraus resultiert, daß manche logisch typisierbare Programme von dem Inferenzmechanismus aus Gründen der Praktikabilität abgelehnt werden. Das selbe Problem tritt bei rekursiven Deklarationen von Instanzen für überladene Funktionen auf.

Wir kehren zu den Anwendungsbeispielen ...oe... oder ...eo... zurück um unsere letzte Designentscheidung zu motivieren. Wenn wir für den Term e einen weiteren überladenen Namen o' wählen erhalten wir die Funktionsanwendung ...oo'.... Wir hatten entschieden, die Instanzauswahl für ein überladenes Programmelement zur Übersetzungszeit durchzuführen. Nun nehmen wir für o die Instanzen o_{1} : τ_{1} → τ und o_{2} : τ_{2} → τ als definiert an und weiter für o' die Instanzen o′_{1} : τ_{1} und o′_{2} : τ_{2}. Es ist offensichtlich die Bedingung zur eindeutigen Instanzauswahl verletzt, denn sowohl die Auswahl ...o_{1}o′_{1}... als auch die Auswahl ...o_{2}o′_{2}... sind wohltypisiert. Wir nennen diese Situation das Mehrdeutigkeitsproblem bei der Instanzauswahl für überladene Programmelemente. Dieses Problem tritt auf weil wir zwei verschiedene Mechanismen zur Auswahl der Instanz angewendet haben. Die Instanz für o wurde in unserem Beispiel durch den Typ seines Arguments in einer Funktionsanwendung festgelegt. Auf der anderen Seite wurde die Instanz für o' durch den Typ ausgewählt der als Argument in einer Anwendung erwartet wird. Um dieses Problem zu vermeiden verwenden wir nur einen Auswahlmechanismus die Auswahl durch den Typ des Arguments. Damit erhalten wir eine Programmiersprache mit überladenen Funktionen.

3.2 System O

Das logische System setzt sich aus 3 Teilen zusammen; die Sprache der Terme, die Sprache der Typen und das Regelsystem welches den Zusammenhang dieser Sprachen in einer Wohlgetyptheitsbeziehung definiert. Wir nehmen an, daß ein algebraischer Datentyp A = (T , a, D, arg, t) wie in Abschnitt 2.3 beschrieben vorhanden sei.

3.2.1 Die Termsprache

Auf der Termebene zeigt sich die Einführung von Überladung dadurch, daß die Termvariablen x in die eindeutigen Namen u und die überladenen Namen o geteilt werden. Die Terme von System O sind dann eine einfache Erweiterung der HM-Sprache von Abschnitt 2.4.

Eindeutige Variablen u ∈ U
Überladene Variablen o ∈ O
Datenkonstruktoren D ∈ D
Variablen  x = u | o
Terme  e = x | D | λu.e | e e′ | let u = e in e′

Man beachte, daß in der Abstraktion λu.e und der let-Anweisung nur eindeutige Variablen u verwendet werden. Ein Programm p besteht aus einer Reihe von Überladungsinstanzdefinitionen und einem Term in dem die überladenen Funktionen genutzt werden können.

p ::= inst o : σ_{T} = e in p | e

Mit der inst-Anweisung wird ein Zweig für eine überladen Funktion zu dem Typkonstruktor T definiert. Die Typannotation σ_{T} ist nicht notwendig da die Typinferenz den allgemeinsten Typ für den Definitionsterm e findet. Die Annotation kann aber genutzt werden um die Allgemeinheit von Typen einzuschränken. Wenn für einige Zweige einer überladenen Funktion die Identitätsfunktion ausgewählt werden soll dann wird die Typannotation gebraucht.

3.2.2 Die Typsprache

Auch die Typsprache ist eine Erweiterung des HM-Typen

Typvariablen  α ∈ V
algebraische Typkonstruktoren  T ∈ T
Typen  τ = α | τ → τ′ | T τ_{1} ... τ_{n}
Typschemen  σ = τ | ∀α.π_{α} ⇒ σ
Einschränkungen von Typvariablen π_{α} = o_{1} : α → τ_{1}, …, o_{n} : α → τ_{n}
wobei i ≠ j ⇒ o_{i} ≠ o_{j}

Aus dem HM-System ist die Zweiteilung der Typsprache in die Typen oder Monotypen τ und die Typschemen oder Polytypen σ übernommen. Zur Behandlung der Überladung werden Typen τ in ihre Konstruktoren T und ihre Argumente τ_{1} … τ_{n} zerlegt. Um bei dieser Typzerlegung einheitlich zu verfahren werden Funktionstypen τ → τ′ in einen zweistelligen Typkonstruktor (→) mit der Argumentbelegung ττ′ zerlegt.

An den Typschemen zeigt sich die Erweiterung der Überladung. Wie in HM besteht ein Typschema σ aus einem Typ τ dem Körper oder der Matrix des Typschemas und einem Präfix von Variablenquantifikationen. In Erweiterung zu HM ist die Quantifikation einer Typvariable α durch eine Menge von Einschränkungen π_{α} auf die Typvariablen beschränkt. In HM können quantifizierte Typvariablen mit beliebigen

(TAUT) Γ ⊢ x : σ (x : σ ∈ Γ)  \frac{Γ ⊢ e : σ Γ, u : σ ⊢ e′ : τ}{Γ ⊢ let u = e in e′ : τ}  (LET)

(→I)  \frac{Γ, u : τ ⊢ e : τ′}{Γ ⊢ λu.e : τ → τ′}  \frac{Γ ⊢ e : τ′ → τ  Γ ⊢ e′ : τ′}{Γ ⊢ e e′ : τ}  (→E)

(∀I) \frac{Γ, π_{α} ⊢ e : σ (α ∉ tv(Γ))}{Γ ⊢ e : ∀α.π_{α} ⇒ σ}  \frac{Γ ⊢ e : ∀α.π_{α} ⇒ σ Γ ⊢ [τ/α]π_{α}}{Γ ⊢ e : [τ/α]σ} (∀E)

Abbildung 3.1: Kernregel des System O .

Typen instantiiert werden. Dagegen ist in System O eine Instantiierung nur zulässig wenn die Einschränkungen erfüllt werden können. In dem Regelsystem wird dieser Instantiierungsmechanismus formalisiert. Die uneingeschränkte Quantifikation ∀α.{} ⇒ σ entspricht dann der Quantifikation ∀α.σ des HM-Systems.

3.2.3 Das Regelsystem

Das Regelsystem formalisiert die Wohlgetyptheitsaussage Γ ⊢ p : σ d.h. das Programm p erhält den Typ σ, wobei für die freien Variablen x des Programms die Typisierungsannahmen x : σ′ in Γ gesammelt wurden. Diese Typhypothese Γ (kurz: Typothese) kann in drei Bereich aufgeteilt werden:

1. Die Eintragungen u : σ für die eindeutigen Termvariablen aus U. Für jedes Element u ∈ U gibt es höchstens einen Eintrag in Γ.

2. Die Instanzdeklarationen o : σ_{T} für die überladenen Termvariablen aus O. Für jede Kombination eines Typkonstruktors T und eines Namens o ∈ O gibt es höchstens einen Eintrag.

3. Die Überladungseinschränkungen o : τ → τ′ für Termvariablen aus O. Überladungseinschränkungen der Form o : α → τ werden Variableneinschränkungen genannt. Falls alle Überladungseinschränkungen die Form von Variableneinschränkungen haben und für jede Kombination einer Typvariable α und eines Namen o ∈ O höchstens ein Eintrag vorhanden ist so, wird die Typothese normalisiert genannt. Diese Begriffsbildungen führen zu dem algorithmischen System (sh. Kapitel 4)

Das Regelsystem von System O läßt sich durch die Erweiterungen zu HM erklären, Teilung der Termvariablen, beschränkte Quantifikation und Instanzdeklarationen für überladene Funktionen. Wir wollen nun die Änderungen des Kernsystem aus Abbildung 3.1 relativ zu dem logischen System von HM diskutieren. In den Regeln (→ I) und (LET) dürfen nur eindeutige Variablen u benutzt werden, so daß durch die Eigenschaften der Typothese Γ diese Namen eindeutig getypt sind. Die Regel (T AUT) erscheint bekannt jedoch ist hier durch die Eigenschaften der Typothese die Überladung von Namen o ∈ O mit verschiedenen Typen ermöglicht. In den Regeln (∀I) und (∀E) wird die eingeschränkte Quantifikation formal behandelt. Aus der Regel (∀I) ist zu entnehmen, daß die Überladungseinschränkungen o : α → τ im Typ eines Terms e in diesem Term als überladene Funktionen o benutzt wurden. Denn die Prämisse Γ.π_{α} ⊢ e : σ besagt eben, daß die Überladungseinschränkungen o : α → τ ∈ π_{α} als freie Termvariablen von e auftreten können. Bei der Instantiierung eines Typs in der Regel (∀E) wird dann der Argumenttyp der überladenen Funktion o festgelegt. Also muß eine neue Nebenbedingung (relativ zu der (∀E)-Regel in HM) prüfen ob die entsprechende überladene Funktion im Programm existiert. Die zweite Prämisse Γ ⊢ [τ/α]π_{α} (a) der (∀E)-Regel ist eben diese Überprüfung. Formal ist für die Herleitung der Aussage (a) eine weitere Regel notwendig um eine Menge von Variablentypisierungen herzuleiten.

(SET) \frac{Γ ⊢ x_{1} : σ_{1} … Γ ⊢ x_{n} : σ_{n}}{Γ ⊢ x_{1} : σ_{1}, …, x_{n} : σ_{n}}

Eine Herleitung der Aussage der Form (a) benutzt nur die Regel (T AUT) für überladene Namen o ∈ O und die Regel (SET). In der Arbeit [SOW96] wurde diese Beobachtung formalisiert durch die Teilung eines logischen Typsystems in die Wohlgetypheitsaussagen und die Nebenbedingungen der Art (a) welche als Constraintsysteme identifiziert wurden. Auch in der Typinferenz zu System O zeigt sich diese Trennung in einem separaten Algorithmus mkinst zur Auflösung von Überladungseinschränkungen. Zur Vervollständigung des logischen Systems ist eine Typisierungsregel für die Einführung von Überladungsinstanzen notwendig.

(INST) \begin{matrix}(o : σ_{T′} ∈ Γ ⇒ T ≠ T′) \\ Γ ⊢ e : σ_{T} Γ, o : σ_{T} ⊢ p : τ \\ Γ ⊢ inst o : σ_{T} = e in p : τ \end{matrix}

Wie in einer let-Anweisung wird einem Namen ein Term zugeordnet allerdings können einem überladenen Namen o mehrere Instanzterme e zugeordnet sein. Mit der Diskriminanznebenbedingung o : σ_{T′} ∈ Γ ⇒ T ≠ T′ wird sichergestellt, daß eine wohldefinierte Funktion durch die verschiedenen Instanzdefinitionen zu einem Namen o festgelegt wird.

Die Typannotation σ_{T} ist, wie bereits oben erwähnt, optional. Falls keine Typannotation in einem Programm auftritt wird der inferierte Typ zu dem Instanzterm e benutzt. Also wird eine Typannotation nur nötig wenn der inferierte Typ eingeschränkt werden muß um die Diskriminanzeigenschaft zu erfüllen.

Aus der obigen Bemerkung wird deutlich, daß hier von einem logische System dessen Auswahl von Regeln durch Symmetrien begründet werden, zu einer praktisch orientierten Sicht übergegangen wird dessen Auswahl von Regeln durch die Typinferenz und die Semantik von Programmen begründet wird. So ist für den Instanztyp σ_{T} nicht jedes Typschema zulässig sondern es wurde in System O eine Auswahl getroffen dessen Begründung sich aus der Terminierung der Typinferenz ergibt.

\begin{aligned}σ_{T} & = & T α_{1} ... α_{n} → τ & (tv(τ) ⊆ \{α_{1}, …, α_{n}\}) \\ & | & ∀α.π_{α} ⇒ σ′_{T} & (tv(π_{α}) ⊆ tv(σ′_{T})). \end{aligned}

Es wird also erwartet, daß die Instanz einer überladenen Funktion an dem ersten Typkonstruktor T ihres Argumenttyps eindeutig feststellbar ist. Für die Auflösung von Überladungseinschränkungen wird gefordert, daß die Variablenbeschränkungen sich nicht zyklisch betreffen.

In Kapitel 5 wird in einem zweiten Schritt versucht diese syntaktischen Einschränkungen aufzuweichen. Die Einschränkungen waren durch die Realisierung des Typinferenzalgorithmus vorgegeben. In Kapitel 5 werden syntaktische Einschränkungen entwickelt welche semantisch durch die Bedingung der Wohldefiniertheit von überladenen Funktionen begründet sind. Im Kern beschäftigt sich also Kapitel 5 mit einer Neudefinition der Instanztypen und der Diskriminanzbedingung daraus folgt dann eine neue logische (INST)-Regel und neue Verfahren für die Typinferenz.

3.3 Ein Programmbeispiel

Das nun folgende Programmbeispiel soll die Nutzung von Überladung vorführen. In dem Beispiel sollen möglichst allgemeine Versionen des map-Algorithmus entwickelt werden. Die map-Funktion erwartet zwei Arten von Argumenten. Einerseits einen Containerparameter wobei alle Werte welche in dem Container enthalten sind den selben Typ haben sollen und andererseits ein Funktionsparameter wobei die Funktion die Werteinträge verarbeiten kann. Eine Anwendung der map-Funktion soll dann den Funktionsparameter auf alle Einträge des Containers anwenden und als Ergebnis einen Container mit den Resultatseinträgen erzeugen.

Wir beginnen mit einer Definition der map-funktion auf Listen und Bäume. Die Definition der entsprechenden algebraischen Datentypen führen die neuen Typkonstruktoren List und Tree ein. Mit diesen Typkonstruktoren kann die Diskriminanzeigenschaft für Überladung erfüllt werden.

     data List a = Cons (a, List a) | Nil
     data Tree a = Brnch(Tree a, Tree a) |  Leaf a

Die map-Funktion auf Listen ist einfach rekursiv im Fall der Cons-Zellen.

     inst map  Cons(a,l) f = Cons(f a, map l f)
          map  Nil       f = Nil

Falls ein Programm mit diesem Code der Typinferenz übergeben wird so wird folgender allgemeinster Typ berechnet.

map : σList ≡ ∀α.∀β.List α → (α → β) → List β

Die map-Funktion auf Bäumen ist zweifach rekursiv im Fall der Verzweigung Brnch.

     inst  map  Brnch(l,r) f =  Brnch(map l f, map r f)
           map  Leaf a     f =  Leaf (f a)

Man beachte, daß in allen Fällen die Struktur der Liste oder des Baums erhalten bleibt. Die Typinferenz über diesen Code führt zu folgendem Typ.

map : σTree ≡ ∀α.∀β.Tree α → (α → β) → Tree β

Im funktionalen Programmieren wird die map-Funktion gewöhnlich zuerst den Funktionsparameter konsumieren und als zweites den Containerparameter. Diese Definition wäre auch näher an dem Funktorbegriff angelehnt. Bei Umschreibung der obigen Instanzdefinitionen würde die Typinferenz des System O eine Verletzung der Diskriminanzeigenschaft melden. Die überladenen Instanzen von map wären durch das erste Argument nicht festgelegt. In Abschnitt 5.5.2 wird eine erweiterte Typinferenz definiert die auch für solche Fälle die Wohlgetyptheit prüfen kann.

Wir wollen nun das Prinzip diese map-Algorithmus auf Funktionsparameter mit mehreren Argumenten erweitern. Dazu soll die map-Funktion so viele Containerparameter annehmen wie der Funktionsparameter Werteinträge als Parameter akzeptiert. Die mehrparametrige map-Funktion soll so geschrieben sein, daß die vordefinierten Instanzen der map-Funktion weiter nutzbar sind. Als Randbedingung der mehrparametrigen map-Funktion ist darauf zu achten, daß alle Container die selbe Struktur besitzen müssen damit aus den entsprechenden Einträgen ein Argument für den Funktionsparameter zusammengesetzt werden kann. Aus diesem Grund wird das Zusammensetzen von Argumentseinträgen in einem eigenen Algorithmus codiert wobei auch gleichzeitig der Test auf Strukturübereinstimmung von Containern ausgeführt wird. Da die Übereinstimmung fehlschlagen kann muß mit möglicherweise fehlerhaften Daten gearbeitet werden. Dies gibt die folgende algebraische Datentypdefinition wieder.

     data  E a = Err | Ok a

Für die möglicherweise fehlerhaften Daten ist eine neue Form der Funktionsanwendung nötig. Die erweiterte Funktionsanwendung wird als linksassoziativer Infixoperator @ definiert.

     `@' (Ok f)  (Ok a) = Ok (f a)
     `@'   __= Err

Die Funktion zur Argumentbildung wird wie map als eine überladene Funktion definiert mit Instanzen für Listen und Bäume.

     inst  zip  Nil Nil  = Ok Nil
           zip  Cons(a, la)  Cons(b, lb) =
             let  mC l   = Ok (Cons((a,b), l))
             in  (Ok mC) @ (zip la lb)
           zip  __= Err

Die Funktion zip für Listen nimmt also zwei Listen gleicher Länge und erzeugt eine Liste dieser Länge mit mit Tupeleinträgen anderenfalls wird das Fehlerelement erzeugt. Die Typinferenz wird für obigen Code den folgenden Typ berechnen.

zip : ∀α.∀β.List α → List β → E List α × β

Bei der Instanzdefinition für die zip-Funktion ist wieder der Fall der Verzweigung zweifach rekursiv. Die zip-Funktion muß in diesem Fall auch auf die Strukturgleichheit des linken und rechten Unterbaumes achten was in der vorliegenden Codierung durch die Verwendung der erweiterten Funktionsapplikation @ geschieht.

      inst  zip  Leaf a  Leaf b = Ok (Leaf (a,b))
            zip  Brnch(tal, tar)  Brnch(tbl, tbr) =
              let  mB tl tr     =  Ok (Brnch( tl, tr))
              in (Ok mB) @ (zip tal tbl) @ (zip tar tbr)
            zip    __= Err

Die Typinferenz errechnet den erwarteten Typ zur zip-Funktion.

zip : ∀α.∀β.Tree α → Tree β → E Tree α × β

mit Hilfe der zip-Funktion und den bereits definierten map-Funktionen kann die map-Instanz für mehrere Containerparameter sehr einfach formuliert werden. Hier zeigt sich nun die Ausdruckskraft des funktionalen Programmierens in der Möglichkeit Teilaufgaben zu faktorisieren und als höhere Funktionen zu codieren. In dem vorliegenden Beispiel wurde der map-Algorithmus in die Argumenterzeugung für den Funktionsparameter und den bereits vorhandenen map-Algorithmus zerlegt.

      map2conn (lval, rval) mult =
         Ok (\x. map x mult) @ (zip lval rval)

Die Typisierung für dieses Programm errechnet einen Typ der auf den ersten Blick zu allgemein erscheint.

map2conn : {map : δ → γ → ϵ, zip : α → β → E δ} ⇒ α × β → γ → E ϵ

Aus dem obigen Typ ist nicht mehr abzulesen, daß der zweite Parameter (hier γ) der map-Funktion eine Funktion sein muß. Es ist auch nicht zu erkennen, daß die Containerparameter (hier α und β) von dem selben Typ sein müssen. Diese Nebenbedingungen ergeben sich erst aus der Analyse der zip und map Instanzen. Da nun zip und map als Überladungseinschränkungen in dem Typ auftreten sind diese Bedingungen also auch in dem Typ reflektiert.

Der aufmerksame Leser wird sich fragen wieso die map-Funktion für zwei Containerargumente nicht den Name map trägt und als weitere Überladungsinstanz definiert wurde. Denn durch den Typkonstruktor für zweitstellige Tupel sollte der Typ dieser map-Instanz auch die Diskriminanzeigenschaft erfüllen. Ein zweiter Blick zeigt jedoch, daß die Bedingung für Typvariablen verletzt ist (im Typ treten andere Typvariablen als α und β aus dem Argumenttyp der überladenen Funktion auf).

Mit den gegebenen map-Funktionen und der map-Funktion auf zwei Containerparametern sind nun die Zutaten vorhanden um map-Funktionen auf mehreren Containerparametern zu definieren. Wir führen hier noch das Beispiel für map auf drei Containerparametern vor.

      map3conn (val1, val2, val3) tripl_conn =
        map2conn (val2, val3) (\tupval -> map2conn (val1, tupval) connect)
        where  connect (x, (y, z)) = tripl_conn (x, y, z)

Bereits der Typ der zweiparametrigen map-Funktion erforderte einige Analyse um zu erkennen, daß dieser Typ tatsächlich die erwartete Struktur der map-Funktion beschreibt. In dem Fall der vorliegenden Funktion map3conn werden für jeden der zwei map2conn-Aufrufe die zugehörigen Überladungseinschränkungen in den Typ übernommen. Der resultierende Typ ist für Programmierer unbrauchbar. Hier zeigt sich, daß die Typinferenz dem Programmierer tatsächlich Aufgaben abnimmt die ansonsten großen Aufwand bedeutet hätten.

Algorithmisches System

Die Abbildungen 4.2 und 4.1 stellen den Algorithmus zur Typinferenz und den Unifikationsalgorithmus für System O dar. Genauer handelt es sich bei dem Algorithmus um eine Typrekonstruktion. Der Unterschied zwischen Rekonstruktion und Inferenz bei der Typherleitung besteht darin, daß in ersterem auch Typannotationen geprüft werden während in letzterem keine Annotationen auftreten können. Im Vergleich zu Milner’s Algorithmus W [Mil78] sind zwei Erweiterungen zu bemerken.

• Im Fall einer Variablenbindung ist der Unifikationsalgorithmus erweitert worden. Falls eine Variable α an einem Typ τ gebunden wird müssen die Einschränkungen Γ_{α} erfüllt sein. Die Funktion mkinst rechnet eine Normalisierung aus auf die Frage ob der Typ τ die Einschränkungen Γ_{α} erfüllt.

Die Normalisierung besteht darin, daß alle Einschränkungen die determiniert sind aufgelöst werden. Dabei sind die determinierten Einschränkungen diejenigen die auf eine einzige Art der Auflösung festgelegt sind. Der Auflösungsschritt besteht darin diese einzige Möglichkeit zu finden und deren Voraussetzungen in die Einschränkungsmenge aufzunehmen. Wenn keine determinierte Einschränkung mehr vorhanden ist, wird die Einschränkungsmenge normalisiert genannt.

• Die Funktion tp wurde um einen Fall erweitert in dem die Deklaration von Instanzen inst o : σ_{T} = e in p typisiert wird. Dies ist ein Rekonstruktionsfall falls der Instanztyp σ_{T} deklariert wurde. In diesem Fall muß geprüft werden, daß der berechnete Typ σ′_{T} für den Überladungsausdruck weniger allgemein ist als der deklarierte Typ σ_{T} .

Im folgenden benutzen wir die Abkürzungen:

\begin{aligned}Γ_{α} & = & \{o : α → τ | o : α → τ ∈ Γ\} \\ Γ_{A} & = & ∪_{α∈A} Γ_{α} \end{aligned}

tp  : (p, Γ, S) → (τ, Γ, S)
tp (u, Γ, S) = if u : σ ∈ Γ
then newinst (σ, Γ, S)
tp (o, Γ, S) = newinst (∀β∀α.(o : α → β) ⇒ α → β, Γ, S)

tp (λu.e, Γ, S)

= let α a new type variable
(τ, Γ_{1}, S_{1}) = tp (e, Γ ∪ {u : α}, S)
in (α → τ, Γ_{1}, S_{1})

tp (e e′, Γ, S)

= let (τ_{1}, Γ_{1}, S_{1}) = tp (e, Γ, S)

(τ_{2}, Γ_{2}, S_{2}) = tp (e′, Γ_{1}, S_{1}) α a new type variable (Γ_{3}, S_{3}) = unify (τ_{1}, τ_{2} → α) (Γ_{2}, S_{2})

in (α, Γ_{3}, S_{3})

tp (let u = e in e′, Γ, S)

= let (σ, Γ_{1}, S_{1}) = gen (tp (e, Γ, S))
in tp (e′, Γ_{1} ∪ {u : σ}, S_{1})

tp (inst o : σ_{T} = e in p, Γ, S)

= let (σ′_{T} , Γ_{1}, S_{1}) = gen (tp (e, Γ, S))

(τ_{2}, Γ_{2}, S_{2}) = skolemize (σ_{T} , Γ_{1}, S_{1}) (τ_{3}, Γ_{3}, S_{3}) = newinst (σ′_{T} , Γ_{2}, S_{2})

in if ∀o:σ_{T′} ∈ Γ. T ≠ T′ ∧

unify(τ_{2}, τ_{3})(Γ_{3}, S_{3}) defined then

tp (p, Γ_{1} ∪ {o : σ_{T} }, S_{1})

Abbildung 4.1: Algorithmus zur Typinferenz für System O unify : (τ, τ) → (Γ, S) → (Γ, S) unify (τ_{1}, τ_{2}) (Γ, S) = case (Sτ_{1}, Sτ_{2}) of

(α, α) ⇒

(Γ, S) (T \overline{τ}_{1}, T \overline{τ}_{2}) ⇒

foldr unify (Γ, S) (zip (\overline{τ}_{1}, \overline{τ}_{2})) (α, τ), (τ, α) where α ∉ tv(τ) ⇒

foldr mkinst (Γ\Γ_{α}, [τ/α] ∘ S) Γ_{α}

mkinst : (o : α → τ) → (Γ, S) → (Γ, S) mkinst (o : α → τ) (Γ, S) = case Sα of

β ⇒ if ∃o : β → τ′ ∈ Γ then unify (τ, τ′) (Γ, S) else (Γ ∪ {o : β → [β/α]τ}, S)

T \overline{τ} ⇒ if !∃o : σ_{T} ∈ Γ then let (p, T α_{p(1)} … α_{p(n)} → τ′, C) = struct(σ_{T} , Γ, S)

in uninfy (τ, τ′)(doinst(1, p, C, α)(Γ, S))

doinst : (N, Π_{N}, C, α) → (Γ, S) → (Γ, S) doinst (i, p, C, α)(Γ, S) = case C of

C′.π_{β} ⇒

doinst (i + 1, p, C′, α) (fold mkinst (Γ, [Sα ↓ p(i)/β] ∘ S)π_{β}) ∅ ⇒ (Γ, S)

Abbildung 4.2: Algorithmus für die erweiterte Unifikation

newinst  : (σ, Γ, S) → (τ, Γ, S)
newinst (∀α.π_{α} ⇒ σ, Γ, S)
= let β neue Typvariable
in newinst ([β/α]σ, Γ ∪ [β/α]π_{α}, S)
newinst (τ, Γ, S)
= (τ, Γ, S)

skolemize : (σ, Γ, S) → (τ, Γ, S)
skolemize (∀α.π_{α} ⇒ σ, Γ, S)
= let T neuer Typkonstruktor der Stelligkeit 0
in skolemize ([T/α]σ, Γ ∪ [T/α]π_{α}, S)
skolemize (τ, Γ, S)
= (τ, Γ, S)
gen  : (τ, Γ, S) → (σ, Γ, S)
gen (σ, Γ, S) = if ∃α.α ∈ tv(Sσ) \ tv(S(Γ\Γ_{α}))
then gen (∀α.Γ_{α} ⇒ σ, Γ\Γ_{α}, S)
else (σ, Γ, S)

Abbildung 4.3: Funktionen die zur Definition des Algorithmus der Typinferenz benötigt werden

Wir benutzen zwei Operationen foldr und fold auf Listen und Mengen. Die linksassotiative Faltung foldr sei wie in Haskell definiert. Die Faltung fold auf Menge sei fold ⊕ z {x_{1}, ..., x_{n}} = x_{1} ⊕ … ⊕ x_{n} ⊕ z wobei ⊕ assotiativ und kommutativ sei mit z als neutralem Element.

Wie oben bereits bemerkt hängt die Termination von unify und mkinst von der syntaktischen Einschränkung der Instanztypen σ_{T} ab :

\begin{aligned}σ_{T} & = & T α_{1} ... α_{n} → τ & (tv(τ) ⊆ \{α_{1}, …, α_{n}\}) \\ & | & ∀α.π_{α} ⇒ σ′_{T} & (tv(π_{α}) ⊆ fv(σ′_{T})). \end{aligned}

Wir zeigen nun an einem Beispiel weshalb σ_{T} parametrisch in den Typargumenten des Konstruktors T sein muß. Der problematische Fall im Beweis der Termination für tp ist die Prozedur mkinst. Bei Ausführung der Prozedur mkinst können neue Einschränkungen auf Variablen in die Typothese eingefügt werden. Darum läßt sich bei dem Beweis der Termination nicht annehmen, daß die Typothese kleiner wird während der Berechnung. Bei dem Terminationsbeweis wird stattdessen die Eigenschaft benutzt, daß während der Berechnung keine neuen Typvariablen eingeführt werden. Die syntaktischen Einschränkungen auf die Form der Instanztypen σ_{T} führen zu dieser Eigenschaft. Die syntaktischen Restriktionen auf σ_{T} schränken den Argumenttyp des Körpers so ein, daß er nur die Form T α_{1} ... α_{n} haben kann. Um diese Einschränkung zu rechtfertigen betrachte man folgendes Programm und das Vorgehen zu seiner Typisierung, wobei k ∈ K_{T}.

p = let (;) x y = y in
inst o : ∀α.o : α → α ⇒ T (T α) → α
= λk(k x).o x
in λx.λy.λf. o x; o y; f (k y) ; fx

Die Berechnung zur Typisierung des Programms p startet mit dem Funktionsaufruf tp(p, ∅, id) dies führt zu dem Aufruf tp(f x, Γ, S), wobei bereits folgende Einträge in die Typothese eingefügt wurden x : α, y : β, f : T β → δ ∈ Γ. Die Anwendung der Funktion f auf das Argument x führt zu dem Aufruf der Unifikation unify(α, T β)(Γ, S), wobei folgende Bedingungen gültig sind:

• σ_{T} = ∀α.o : α → α ⇒ T (T α) → α

• Γ ⊇ {o : α → α, o : β → β, o : σ_{T} },

• S ist eine Substitution mit α, β ∉ dom(S).

Ausführung von unify löst die Bearbeitung von mkinst(o : α → α)(Γ \ Γ_{α}, S′) aus, wobei in der Substitution bereits die Bindung von α durchgeführt wurde, also S′ = [T β/α] ∘ S. Die Ausführung von mkinst führt wegen der aktuellen Argumente zu folgende zwei Aufrufen :

1. newinst(σ_{T} , Γ \ Γ_{α}, S′) = (T (T γ) → γ, Γ′, S′) wobei Γ′ ⊇ {o : β → β, o : γ → γ, o : σ_{T} } und γ eine neue Typvariable ist.

2. unify(α → α, T (T γ) → γ)(Γ′, S′).

Da S′α = T β gilt, führt die Bearbeitung von 2. zu einem Versuch T β und T (T γ) (d.h. die Argumenttypen der beiden Funktionstypen) zu unifizieren. Nach Reduzierung des Typkonstruktors T wird der Aufruf unify(β, T γ)(Γ′, S′) ausgelöst. Dieser Aufruf von unify ist äquivalent zu obigem Aufruf unify(α, T β)(Γ, S) modulo der Umbenennung von α, β zu β, γ. Also wird unify in eine Endlosschleife an diesem Punkt eintreten. Die Idee zur Konstruktion solcher Programmbeispiele hängt an der Einfügung von neuen Einschränkungen für Typvariablen durch die Funktion newinst. Wenn diese neu eingefügten Einschränkungen Kopien von bereits früher vorhandenen Einschränkungen modulo Variablenumbenennung sind kann das zu einer Endlosschleife führen. Die restlichen syntaktischen Einschränkungen für die Instanztypen σ_{T} lassen sich auch mit diesem Vorgehen motivieren. Aus diesen Gegenbeispielen folgt auch das Vorgehen zum Beweis der Termination des Typisierungsalgorithmus.

4.1 Eigenschaften von System O

Im folgenden werden die Korrektheits- und Vollständigkeitseigenschaften für die Funktionen unify und tp vorgestellt. Dazu werden erst technische Begriffe für Zustände und Relationen in der Typinferenz eingeführt. Mit den hier definierten Begriffen lassen sich die Eigenschaften für die Unifikation sehr gut zeigen. Die Eigenschaften der Typinferenz sind aber mit den Begriffen der Abschnitte 4.3.1 - 4.3.4 besser zu behandeln. Die Beweise sind von der der Arbeit [Che94] inspiriert, es wurden aber doch später völlig neue Beweistechniken entwickelt.

Definition. Eine Konfiguration ist ein Paar (Γ, S) bestehend aus einer Typothese Γ und einer Substitution S, so daß für alle Typvariablen α ∈ dom(S)Γ_{α} = ∅.

Definition. Im folgenden wird eine Halbordnung ⪯ auf Substitutionen und Konfigurationen definiert und eine Halbordnung ⪯_{Γ} auf Typschemen. Wir sagen Y ist allgemeiner als X wenn die Beziehung X ⪯ Y gilt.

• S′ ⪯ S gdw. es eine Substitution R gibt mit S′ = R ∘ S.

• (Γ′, S′) ⪯ (Γ, S) gdw. S′ ⪯ S, S′Γ′ ⊢ S′Γ_{dom(S′)} und Γ′ ⊇ Γ \ Γ_{dom(S′)}.

• σ′ ⪯_{Γ} σ gdw. für alle u ∉ dom(Γ), Γ ⊢ u : σ folgt Γ ⊢ u : σ′.

Definition. Ein erweitertes Unifikationsproblem ist ein Paar von Tupeln (τ_{1}, τ_{2})(Γ, S) wobei τ_{1}, τ_{2} Typen sind und (Γ, S) eine Konfiguration ist.

Eine Konfiguration (Γ′, S′) wird unifizierende Konfiguration genannt für das Unifikationsproblem (τ_{1}, τ_{2})(Γ, S) gdw. (Γ′, S′) ⪯ (Γ, S) und S′τ_{1} = S′τ_{2}.

Eine unifizierende Konfiguration (Γ′, S′) ist die allgemeinste gdw. (Γ′′, S′′) ⪯ (Γ′, S′) für jede andere unifizierende Konfiguration (Γ′′, S′′) gilt.

Definition. Ein Typisierungsproblem ist ein Tripel (p, Γ, S) wobei (Γ, S) eine Konfiguration ist und p ein Programm mit der Eigenschaft fv(p) ⊆ dom(Γ).

Eine Typisierungslösung eines Typisierungsproblems (p, Γ, S) ist ein Tripel (σ, Γ′, S′) wobei (Γ′, S′) ⪯ (Γ, S) und S′Γ′ ⊢ p : S′σ gilt.

Eine Typisierungslösung (σ, Γ′, S′) ist die Allgemeinste wenn für jede andere Typisierungslösung (σ′′, Γ′′, S′′) die Eigenschaften (Γ′′, S′′) ⪯ (Γ′, S′) und S′′σ′′ ⪯_{S′′Γ′′} S′′σ gelten.

Satz 4.1.1 Sei (τ_{1}, τ_{2})(Γ, S) ein erweitertes Unifikationsproblem

(a) Wenn unify(τ_{1}, τ_{2})(Γ, S) = (Γ′, S′) dann ist (Γ′, S′) die allgemeinste unifizierende Konfiguration für (τ_{1}, τ_{2})(Γ, S).

(b) Wenn unify(τ_{1}, τ_{2})(Γ, S) fehlschlägt, dann gibt es keine unifizierende Konfiguration für (τ_{1}, τ_{2})(Γ, S).

Satz 4.1.2 Sei (p, Γ, S) ein Typisierungsproblem

(a) Wenn tp (p, Γ, S) = (σ, Γ′, S′) dann ist (σ, Γ′, S′) die allgemeinste Lösung von (p, Γ, S).

(b) Wenn tp (p, Γ, S) fehlschlägt dann hat (p, Γ, S) keine Lösung.

Als ein Korollar von Satz 4.1.2 erhalten wir, daß jedes Programm einen prinzipiellen Typ hat, der durch den Algorithmus tp gefunden wird.

Korrolar 4.1.3 (prinzipielle Typeigenschaft) Sei (p, Γ, id) ein Typisierungsproblem, so daß tv(Γ) = ∅.

(a) Angenommen gen (tp (p, Γ, id)) = (σ′, Γ′, S) und σ = Sσ′. Dann gilt :

Γ ⊢ p : σ  und
Γ ⊢ p : σ′′ ⇒ σ′′ ⪯_{Γ} σ, für alle Typschemen σ′′.

(b) Wenn tp (p, Γ, id) fehlschlägt dann gibt es kein Typschema σ, so daß Γ ⊢ p : σ gilt.

4.1.1 Semantische Korrektheit

In der Arbeit [OWW95] wurde von Martin Odersky ein Idealmodell [DM86] für System O vorgestellt und der Satz der semantischen Korrektheit bewiesen. Das Neuartige dieses Resultats ist, daß erstmals eine kompositionale Semantik für ein Typsystem mit Überladung und parametrischer Polymorphie vorgestellt wurde. Für einen gegebenen algebraischen Datentyp A = (T , a, D, arg, t) wurde eine CPO mit folgender Isomorphiegleichung als gegeben angesehen :

V ≅ V → V + Σ_{D∈D}DV_{1} … V_{ad(D)} + {wrong}

wobei ad(D) die Stelligkeit des Datenkonstruktors D angibt. Durch V ist also die Wertmenge modelliert. Eine Termumgebung η belegt die eindeutigen Namen aus U mit Werten aus V und die überladenen Namen aus O mit steigen Abbildungen aus V → V.

η : U → V ∪ O → (V → V)

Für die Modellierung der Instanzdefinitionen wurde eine neue Konstruktion entwickelt:

⟦inst o : σ_{T} = e in p⟧η =

wenn ⟦e⟧η ∈ V → V dann

⟦p⟧η[o := extend(T, ⟦e⟧η, η(o))] sonst W

wobei

extend((→), f, g) =

λv.wenn v ∈ V → V dann f(v) sonst g(v) extend(D, f, g) =

λv.wenn ∃k ∈ K_{D}.v ∈ k \underbrace{V … V}_{arity(k)} dann f(v) sonst g(v).

Als Menge der Teilräume I(V) zur Modellierung der Typen wurden die Ideale ausgewählt. Die Ideale sind durch die Teilmengenbeziehung geordnet. Mit gegebener Termumgebung η kann definiert werden, daß ein Ideal I ∈ I(V) semantische Instanz eines Typschemas σ ist kurz η ⊧ I ⊆ σ. Dazu muß für jede kompatible Belegung [I′/α] von gebundenen Typvariablen mit Idealen I′ die semantische Instanzbeziehung η ⊧ I ⊆ [I′/α]σ′ für σ ≡ ∀α.π_{α} ⇒ σ′ gelten. Eine Belegung [I′/α] ist kompatibel wenn jede gebundene Überladungseinschränkung o : α → τ ∈ π_{α} durch die Termumgebung gerechtfertigt werden kann η(o) ∈ ⟦[I′/α]α → τ⟧. Eine Termumgebung η ist kompatibel mit einer Typothese Γ (kurz: η ⊧ Γ) wenn alle Einträge x : σ ∈ Γ der Typothese semantisch passen η(x) ∈ ⟦σ⟧η.

Damit lassen sich die Typschemen mit Überladungseinschränkungen σ interpretieren

⟦σ⟧η = ⋂{I | η ⊧ I ⊆ σ}

und die semantische Typisierungsaussage definieren.

Γ ⊧ e : σ gdw η ⊧ Γ ⟹ ⟦e⟧η ∈ ⟦σ⟧η

Nach dem Beweis, daß das Fehlerelement nicht in der Interpretation eines Typschemas enthalten ist (wrong ∉ ⟦σ⟧) und dem Beweis der semantischen Korrektheit (Γ ⊢ e : σ ⟹ Γ ⊧ e : σ) folgt das Wohlgetypheitsprinzip für System O :

Γ ⊢ e : σ ∧ η ⊧ Γ ⟹ ⟦e⟧η ≠ wrong

4.2 Beweis der Typeigenschaften

4.2.1 Erweiterte Unifikation

Eine Substitution auf Typvariablen ist eine idempotente Abbildung von Typvariablen auf Typen, wobei die Abbildung nur auf einer endlichen Menge von Variablen verschieden zur Identitätsabbildung ist. Eine Substitution kann strukturell erweitert werden zu einer Abbildung zwischen Typen, Typschemen, Typothesen, Aussagen und Herleitungen. Man beachte, daß die Anwendung einer Substitution auf einer korrekten Herleitung im System O wieder zu einer korrekten Herleitung in System O führt. Wir nehmen im folgenden an, daß alle gebunden Typvariablen paarweise verschieden sind mit allen freien Typvariablen. Dies kann immer erreicht werden durch Umbenennung der gebundenen Typvariablen. Sei id die Identitätsabbildung und [τ/α] die Ersetzung von α durch τ, diese Substitution wird auch Bindung von α durch τ genannt. Die Aneinanderreihung RS der Substitutionen S und R bezeichnet die Komposition der beiden Abbildungen, wobei zuerst die Substitution S angewandt wird und danach die Substitution R angewandt wird. Wir definieren S ≤^{T} R gdw. T S = R und als Kurzschreibweise S ≤ R gdw. ∃T.S ≤^{T} R. In [LMM87] ist der Satz zu finden, daß die Menge der Substitutionen mit der Relation ≤ ein vollständiger unterer Halbverband ist. Seien die zwei Typen τ_{1}, τ_{2} gegeben, dann ist ein Unifikator dazu eine Substitution S welche die Gleichung Sτ_{1} = Sτ_{2} erfüllt. Ein allgemeinster Unifikator S erfüllt die Beziehung S ≤ S′ für jeden anderen Unifikator S′, wir notieren dieses mit mgu(τ_{1}, τ_{2}) = S. Es ist eine einfache Folgerung, daß die allgemeinsten Unifikationen äquivalent sind modulo Variablenumbenennung. Nun wird der Zustand während einer Typisierungsberechnung definiert. Bei den Beweisen zur Termination der Typisierungsfunktionen wird dann gezeigt das bei jeden Schritt ein Maß auf dem Typisierungszustand verringert wird. Aus der Definition des Maßes des Typisierungszustands ist offensichtlich, daß dieses Maß eine wohlfundierte Relation auf die Zustände definiert. Mit diesen beiden Eigenschaften ergibt sich die Terminierung.

Definition. (Typisierungszustand, unify und mkinst auf Typisierungszuständen, das Maß auf Typisierungszustände) Wir definieren ein Tupel T = (τ_{1}, τ_{2}, Γ, S, r) genannt Typisierungszustand mit den zwei Typen τ_{1}, τ_{2}, einer Konfiguration (Γ, S) und einer Überladungseinschränkung auf eine Typvariable α. Also habe r die Form o : α → τ. Wir definieren die Operation ↘ zur Einsetzung einer Konfiguration in einen Typisierungszustand durch

(Γ′, S′) ↘ (τ_{1}, τ_{2}, Γ, S, r) := (τ_{1}, τ_{2}, Γ′, S′, r)

Es seien folgende Variablenmengen definiert :

\begin{aligned}dom(S) & := & \{α|Sα ≠ α\} \\ V ar(T ) & := & tv(S(τ_{1}, τ_{2}, α → τ, Γ)) \end{aligned}

Die Menge V ar(T ) ist also die Menge der freien Typvariablen in einem Typisierungszustand. Man beachte, daß aus α ∈ dom(S) folgt α ∉ V ar(T ), also verringert jede Variablenbindung die Anzahl der freien Variablen.

Eine Typisierungsfunktion ist definiert als eine partielle Abbildung f von einem Typisierungszustand T_{1} zu einem Typisierungszustand T_{2} (in Kurzschreibweise: fT_{1} ⇝ T_{2}) gdw. :

f T_{1} = \{ \begin{matrix}kein Wert & halte mit Fehlermeldung \\ T_{2} & terminiere mit Ergebnis T_{2} \end{matrix}

Nun definieren wir unify und mkinst als Typisierungsfunktionen. Wenn der Aufruf unify(τ_{1}, τ_{2})(Γ, S) mit dem Ergebnis (Γ′, S′) terminiert oder mit einer Fehlermeldung anhält dann gelte :

unify T ⇝ (Γ′, S′) ↘ T

Wenn der Aufruf mkinst(o : α → τ)(Γ, S) dem Ergebnis (Γ′, S′) terminiert oder mit einer Fehlermeldung anhält dann gelte :

mkinst T ⇝ (Γ′, S′) ↘ T

Wir definieren rekursiv ein Maß |τ| auf Typen τ

falls τ = α  : |τ| := 1
falls τ = T τ_{1} … τ_{n} : |τ| := 1 + ∑_{i=1}^{n} |τ_{i}|
falls τ = τ_{1} → τ_{2} : |τ| := 1 + |τ_{1}| + |τ_{2}|

Das Maß auf Typen wird nun erweitert zu einem Maß auf den Typisierungszustand. Dieses Maß auf den Typisierungszustand wird dann benutzt um mit der Methode der wohlfundierten Induktion die Eigenschaften von unify und mkinst zu beweisen.

|T | := (|V ar(T )|, |Sα|, |Sτ_{1}|, |Sτ_{2}|)

wobei |V ar(T )| die Kardinalität der Menge der freien Variablen ist und α die beschränkte Variable der Einschränkung r = o : α → τ ist. Die Beziehung |T | > |T′| ist definiert durch die Benutzung der lexikographische Ordnung auf Tupel von natürlichen Zahlen.

Wie in Abschnitt 4.1 erläutert sind die Instanztypen σ_{T} für eine Typkonstruktor T definiert durch die syntaktischen Einschränkungen :

σ_{T} = T α_{1} ... α_{n} → τ  (tv(τ) ⊆ {α_{1}, …, α_{n}})
| ∀α.π_{α} ⇒ σ′_{T}  (tv(π_{α}) \ {α} ⊆ fv(σ′_{T})).
π_{α} = o_{1} : α → τ_{1}, …, o_{n} : α → τ_{n}
(n ≥ 0, wobei o_{1}, …, o_{n} paarweise verschieden)

Die syntaktischen Einschränkungen ergeben das folgende Lemma.

Lemma 4.2.1 (Struktur von σ_{T}) Sei σ_{T} ein Instanztyp mit einem Typkonstruktor T der Stelligkeit n = ar(T). Dann gibt es eine Permutation p : {1, …, n} → {1, …, n}, so daß σ_{T} die folgende Struktur hat :

σ_{T} = ∀α_{1}.π_{α_{1}} ⇒ … ∀α_{n}.π_{α_{n}} ⇒ T α_{p(1)} … α_{p(n)} → τ

wobei tv(π_{α_{i}}) ⊆ {α_{1}, …, α_{i}} für i ∈ {1, …, n}.

Definition. (Struktur eines Instanztyps) Sei (Γ, S) eine Konfiguration, dann definieren wir :

struc(σ_{T} , Γ, S) ↦ (p, T α_{p(1)} … α_{(n)} → τ, C)

wobei C = π_{α_{1}} … π_{α_{n}} die Sequenz der umbenannten Einschränkungen ist. Die Umbenennung führt die neuen Variablennamen α_{1} … α_{n} für die in σ_{T} gebundenen Variablen ein.

Weiter sei der Zugriff auf die Komponenten eines Typ durch T τ_{1} … τ_{n} ↓ k ↦ τ_{k} für k ∈ {1, …, n} definiert.

Definition. (doinst Typisierungsfunktion) Sei (τ_{1}, τ_{2}, Γ, S, o : α → τ) ein Typisierungszustand mit :

• Sα = T \overline{τ}

• !∃o : σ_{T} ∈ Γ

• σ_{T} = ∀α_{1}.π_{α_{1}} ⇒ … ∀α_{n}.π_{α_{n}} ⇒ T α_{p(1)} … α_{p(n)} → τ

• {α_{1}, …, α_{n}} ∩ V ar(T ) = ∅

dann ist die Notation doinst T ⇝ (Γ′, S′) ↘ T eine Kurzform für doinst (1, p, π_{α_{1}} … π_{α_{n}}, α)(Γ, S) ⇝ (Γ′, S′)

4.2.2 Terminierung von unify

Der Algorithmus der Funktion mkinst wie in Abbildung 4.2 zu sehen hat die Eigenschaft, daß niemals eine freie Typvariable eingeführt wird. Der einzige Fall an dem virtuell eine Typvariable eingeführt wird ist der erste Zweig in doinst, doch hier wird auch gleich eine Bindung durchgeführt.

Da die Funktionen unify, mkinst und doinst mutuell rekursiv definiert sind, muß die Terminierung der drei Funktionen in einem Beweis vorgenommen werden. Durch Induktion auf das Maß |T | wird die Terminierung gezeigt, dabei ist in jedem Induktionsschritt nachzuweisen, daß bei einem Schritt in der Berechnung das Maß des Typisierungszustands kleiner wird. Da jede absteigende Folge von lexikographisch geordneten Tupeln von natürlichen Zahlen endlich ist, folgt aus obiger Argumentation die Terminierung der 3 Funktionen.

Ein Beweis dieser Struktur wird uns im nächsten Abschnitt wieder begegnen, denn der Beweis für die Korrektheit und Vollständigkeit der der Funktion unify benutzt dieselben Fallunterscheidungen.

Lemma 4.2.2 Die Berechnung von unify T terminiert mit dem Ergebnis (Γ′, S′) oder hält mit einer Fehlermeldung an. (kurz notiert: ∀T ∃(Γ′, S′). unify T ⇝ (Γ′, S′) ↘ T ) Beweis: Wir untersuchen die die Fälle für die Werte des TypisierungszustandT = (τ_{1}, τ_{2}, Γ, S, r) in dem unify Algorithmus :

Sτ_{1} = α, Sτ_{2} = β Terminierung ist trivial.

Sτ_{1} = T \overline{τ_{1}}, Sτ_{2} = T \overline{τ_{2}} In diesem Fall wird eine Reihe von unify Aufrufen ausgelöst. Die aktuellen Argumente τ_{1}, τ_{2} dieser Aufrufe sind Unterbäume der gegebenen Typbäume T \overline{τ_{1}}, T \overline{τ_{2}}. Also folgt aus der Definition des Maßes auf Typisierungszustände, daß die ausgelösten unify Aufrufe mit Typisierungszuständenvon niedrigerem Maß arbeiten, also ist die Induktionshypothese anwendbar. Da die Sequenz der Typen \overline{τ_{1}}, \overline{τ_{2}} endlich ist, ist dadurch die Termination für diesen Fall gezeigt.

Sτ_{1} = α, Sτ_{1} = τ Nun sind zwei Fälle für die Menge der Einschränkungen Γ_{α} auf die zu bindende Typvariable α zu untersuchen.

Γ_{α} = ∅ Die Terminierung ist trivial da nur die Bindeoperation [τ/α]S auszuführen ist.

Γ_{α} ≠ ∅ In diesem Fall wird die Erfüllbarkeit der Einschränkungen Γ_{α} geprüft. Dazu wird fold mkinst aufgerufen mit dem neuen TypisierungszustandT′ = (τ_{1}, τ_{2}, Γ′, S′, r) wobei bereits die Bindung ausgeführt wurde S′ = [τ/α]S und die Einschränkungen auf die Typvariable α aus der Typothese entfernt wurde Γ′ = Γ \ Γ_{α}. Wegen der Bindung [τ/α] gilt α ∉ V ar(T′) in dem neuen TypisierungszustandT′. Also wurde die erste Komponente des Maß es |T′| im Vergleich zu |T | verringert. Also können wir im folgenden aus der Induktionshypothese folgern, daß Aufrufe unify T′′ mit |T′| ≤ |T′′| terminieren (1) . In den folgenden Fällen haben wir die Struktur des Typs τ und der Einschränkung r′ = o : α → τ′ ∈ Γ_{α} zu untersuchen, welche die aktuellen Argumente der Funktion mkinst bilden : τ = β Es werden zwei Fälle in dem Code der Funktion mkinst unter-

schieden : ∄o : β → τ′′ ∈ SΓ Terminierung ist trivial. ∃o : β → τ′′ ∈ SΓ Nun benutzen wir (1) um die Terminierung

des Unifikationsaufrufs unify(τ′, τ′′)(Γ′, S′) zu erhalten. τ = T \overline{τ} Hier haben wir die Terminierung der Funktion doinst zu zei-

gen. Die Funktion doinst führt einen Schritt in dem Erfüllbarkeitstest für Einschränkungen aus, da für die gebundene Einschränkung r′ = o : α → τ′ ∈ Γ_{α} die Instanzdeklaration o : σ_{T} gefunden wurde. Nun ist zu prüfen ob die Einschränkungen C die sich aus der Struktur des Instanztyps struc(σ_{T} , Γ, S) ↦ (p, T α_{p(1)} … α_{(n)} → τ, C) ergeben auch erfüllbar sind. Man bemerke das die Struktur des Instanztyps σ_{T} endlich ist, also führt die Berechnung der Funktion doinst zu endlich vielen Aufrufen der Funktion mkinst. Der einzigen nichttrivialen Fall des Algorithmus von doinst ist die Behandlung einer nichtleeren Einschränkungssequenz C′.π_{β}. In diesem Fall wird der Aufruf fold mkinst(Γ′, S′′)π_{β} ausgelöst wobei die neue Substitution S′′ = [(S′α ↓ p(i))/β]S′ durch Bindung der Quantifikationsvariable β erzeugt wurde. Nun folgt, daß die neue Bindung S′′β = τ ↓ p(i) ein Teil unseres vorigen Typbaumes ist S′α = τ. Also ist die zweite Komponente der Maß es auf den Typisierungszustandverringert worden, so daß die Induktionshypothese auf die ausgelösten mkinst Aufrufe anwendbar ist. Also terminiert der Algorithmus auch in diesem Fall.

4.2.3 Vollständigkeit und Korrektheit der erweiterten Unifikation

Definition. Sei (Γ, S) eine Konfiguration und r = o : α → τ eine Einschränkung auf eine Typvariable mit α ∈ dom(S), dann wird (r)(Γ, S) ein Einschränkungsproblem genannt. Eine Konfiguration (Γ′, S′) für die die Aussagen S′Γ′ ⊢ o : S′(α → τ) und (Γ′, S′) ≤ (Γ, S) gelten, wird die Lösung des Einschränkungsproblems genannt.

Definition. Sei T = (τ_{1}, τ_{2}, Γ, S, o : α → τ) ein typing state dann wird up = (τ_{1}, τ_{2})(Γ, S) das Unifikationsproblem und rp = (o : α → τ)(Γ, S) das Einschränkungsproblem zu dem typing state genannt.

Im folgenden werden nur Konfigurationen (Γ, S) betrachtet die die folgenden Eigenschaften erfüllen, solche Konfigurationen werden als normalisiert bezeichnet. Alle Konfigurationen (Γ, S) die während der Berechnung einer Typinferenz als Zwischenzustände auftauchen sind normalisiert wenn die Anfangskonfiguration normalisiert sind.

Lemma 4.2.3 (normale Konfigurationen) Es gibt drei Arten von Typbindungseinträgen x : σ ∈ SΓ in der Typothese SΓ.

(Eindeutig) x ist eine eindeutige Variable u ∈ U.

(Überladen) x ist eine überladene Variable o ∈ O und σ ist ein Instanztyp σ_{T}. Desweiteren gibt es für den Typkonstruktor T keinen weiteren Typbindungseintrag o : σ′_{T} ∈ SΓ mit dem selben Typkonstruktor T.

(Einschränkung) x ist eine überladene Variable o ∈ O und der Typ hat die Form Sσ = α → τ. Dieser Fall wird Einschränkung einer Variable genannt (kurz wird die Einschränkung mit dem Namen r notiert). Es gibt in diesem Falle keine weiter Einschränkung o : α → τ′ ∈ SΓ wobei τ ≠ τ′.

Im folgenden werden wir normale Typothesen Γ partitioniert darstellen als Γ = A.D.C. Wobei A eine Typothese ist die nur eindeutige Variablen der Form u : σ enthält. D ist die Menge der konfliktfreien Instanzdeklarationen o : σ_{T} für überladene Variablen. C ist die Menge der konfliktfreien Einschränkungen der Form o : α → τ auf Typvariablen. Wir verwenden den Buchstaben T um die Vereinigung A.D der Typbindungen für eindeutige Variablen und Instanzdeklarationen für überladene Variablen zu benennen und erhalten dann eine Partition Γ = T.C.

Die Invarianz der Normalisierungseigenschaft für Konfigurationen während der Berechnung einer Typisierung ist einfach zu sehen. In allen Fällen von Neueinträgen in die Typothese werden die Nebenbedingungen für Konfliktfreiheit geprüft.

Lemma 4.2.4 (Charakterisierung einer normalisierten Einschränkung) Gegeben eine Einschränkung r = o : α → τ auf die Typvariable α ∈ dom(S). Die Konfiguration (Γ, S) heiß t Normalisierung zu dieser Einschränkung wenn die logische Aussage SΓ ⊢ o : S(α → τ) gültig ist, dann gibt es zwei Fälle für die Herleitung der Aussage :

(Var)  Sα = β ⟹ !∃o : β → Sτ ∈ SΓ
(Konstruktor) Sα = T \overline{τ} ⟹ !∃o : σ_{T} ∈ SΓ
wobei  σ_{T} = ∀α_{1}.π_{α_{1}} ⇒ … ∀α_{n}.π_{α_{n}} ⇒ T α_{p(1)} … α_{p(n)} → τ′
und  \overline{τ} = τ_{1} … τ_{n}
und  S ≥ {τ_{p^{−1}(1)}/α_{1}, …, τ_{p^{−1}(n)}/α_{n}}
und  SΓ ⊢ Sπ_{α_{i}} für i ∈ {1, …, n}
und  Sτ = Sτ′

Beweis: Eine einfache Induktion über die Herleitung der logischen Aussage SΓ ⊢ o : S(α → τ) wobei nur die Regeln (T AUT), (∀I) und (∀E) betrachtet werden müssen.

Für den (Var) Fall ist nur die (T AUT) Regel anwendbar.

Für den (Konstruktor) Fall muß die (T AUT) Regel auf eine Instanzdeklaration o : σ_{T} ∈ SΓ angewendet werden. Dies folgt aus der Struktur von normalisierten Konfigurationen (Γ, S) Lemma 4.2.3. Um die logische Aussage SΓ ⊢ Sr herzuleiten muß die Regel (∀E) für jede quantifizierte Variable α_{i} angewendet werden. Das heißt die Mengen von Einschränkungen π_{α_{i}} müssen durch die Konfiguration (Γ, S) normalisiert werden, wodurch sich die Nebenbedingungen ergeben.

Lemma 4.2.5 (Charakterisierung der Ordnungsrelation auf Konfigurationen) Die Beziehung (Γ, S) ≥ (Γ′, S′) gilt gdw. die Beziehung S ≤^{R} S′ auf den Substitutionen gilt und die logische Aussage S′Γ′ ⊢ S′Γ gilt, wobei die logische Aussage für die normale Konfiguration genau dann gilt wenn folgenden Fallunterscheidungen für die Typbindungen x : σ ∈ SΓ gelten.

• Für Typbindungen die keine Einschränkungen sind x : σ ∈ SΓ ⟹ x : Rσ ∈ S′Γ′.

• Für Einschränkungen r = o : α → τ ∈ SΓ und die Menge von Typvariablen V = dom(S′) \ dom(S) gibt es drei Fälle :

(Statisch − r)  α ∉ V  ⟹ Rr ∈ S′Γ′
(Umbenennung − r) α ∈ V Rα = β ⟹ Rr ∈ S′Γ′
(Bindung − r)  α ∈ V Rα = T \overline{τ} ⟹ Rr ∉ S′Γ′ und S′Γ′ ⊢ S′r

Beweis: Wir benutzen Lemma 4.2.3 die Charakterisierung von Konfigurationen, wobei die Fälle (Eindeutig) und (Überladen) die Fälle von Typbindungen erklären die keine Einschränkungen sind.

Für die Einschränkungen benutzen wir Lemma 4.2.4, so daß der Fall (Umbenennung-r) aus dem Fall (Var) folgt und der Fall (Bindung-r) aus dem Fall (Konstruktor) folgt. Der Fall (Statisch-r) ist eine Folgerung aus der Herleitbarkeit der logischen Aussage S′Γ′ ⊢ S′r. Diese Aussage kann nur mit der Regel (T AUT) hergeleitet werden woraus Rr ∈ S′Γ′ folgt.

Lemma 4.2.6 Die Ordnungsrelation auf Konfigurationen ist transitiv.

Beweis: Die Transitivität der Ordnungsrelation S ≤ S′ auf Substitutionen folgt einfach durch Assotiativität der Komposition auf Substitutionen.

Für die Relation von Konfigurationen haben wir die Implikation (Γ, S) ≥ (Γ′, S′) ∧ (Γ′, S′) ≥ (Γ′′, S′′) ⇒ (Γ, S) ≥ (Γ′′, S′′) zu zeigen. Wir können also die logischen Aussagen S′Γ′ ⊢ S′Γ (1) , S′′Γ′′ ⊢ S′′Γ′ (2) und die Beziehung S′ ≤^{R} S′′ zwischen den Substitutionen benutzen. Offensichtlich ist RS′Γ′ ⊢ RS′Γ = S′′Γ′ ⊢ S′′Γ (3) eine gültige Herleitung die durch Anwendung der Substitution R auf die Herleitung von (1) entsteht. Nun ersetzen wir jede Anwendung der Regel (T AUT) für eine Typbindung x : σ ∈ S′′Γ′ in der Herleitung von (3) durch die Herleitung S′′Γ′′ ⊢ x : σ welche wiederum durch (2) gegeben ist. So erhalten wir die Herleitung für die logische Aussage S′′Γ′′ ⊢ S′′Γ □.

Lemma 4.2.7 (Korrektheit und Vollständigkeit der Unifikation) Sei T = (τ_{1}, τ_{2}, Γ, S, r) ein Typisierungszustanddann gilt :

1. (a) Wenn unify T ⇝ (Γ′, S′) dann ist (Γ′, S′) eine Lösung für das Unifikationsproblem von T .

(b) Wenn (Γ′′, S′′) eine Lösung für das Problem up ist, dann gilt (Γ′′, S′′) ≤ (Γ′, S′).Also ist (Γ′, S′) die allgemeinste Konfiguration für up.

2. (a) Wenn mkinst(r)(Γ, S) ⇝ (Γ′, S′) dann ist (Γ′, S′) eine Lösung des Einschränkungsproblems.

(b) Wenn (Γ′′, S′′) eine weitere Lösung des Einschränkungsproblems ist dann gilt (Γ′′, S′′) ≤ (Γ′, S′).

3. (a) Wenn die Bedingungen Sα = T \overline{τ} und doinst T ⇝ (Γ′, S′) gelten dann ist (Γ′, S′) eine Lösung des Einschränkungsproblems (r)(Γ, S).

(b) Wenn (Γ′′, S′′) eine weitere Lösung des Einschränkungsproblems ist dann gilt die Beziehung (Γ′′, S′′) ≤ (Γ′, S′).

Beweis: Als Beweismethode verwenden wir Induktion auf das Maß des TypisierungszustandT = (τ_{1}, τ_{2}, Γ, S, r). Dazu muß schrittweise gezeigt werden, daß der Algorithmus die gesuchte Lösung (Γ′, S′) berechnet die dann die allgemeinste Lösung ist.

Wir untersuchen als erstes die Fälle für die Argumente Sτ_{1} und Sτ_{2} der Funktion unify.

Sτ_{1} = α, Sτ_{2} = β Dies ist der triviale Fall in dem wir offensichtlich die Aussagen 1(a) & (b) erhalten wenn wir (Γ′, S′) =^{def} (Γ, S) setzen.

Sτ_{1} = T \overline{τ}_{1}, Sτ_{2} = T \overline{τ}_{2}

1(a) Für die Argumente \overline{τ}_{1} = τ′_{1} … τ′_{n} und \overline{τ}_{2} = τ̃_{1} … τ̃_{n} des Typkonstruktor erhalten wir für jeden Index i ∈ {1, …, n} die Beziehungen :

|Sτ′_{i}| < |Sτ_{1}| und |Sτ̃_{i}| < |Sτ_{2}| (1)

Wir haben die Beweisverpflichtungen unify T_{i−1} ⇝ T_{i} (2) zu zeigen. Wobei die Aussage 1(a) gültig ist für die Indizes i ∈ {1, …, n} mit den TypisierungszuständeT_{i} = (τ′_{i}, τ̃_{1}, Γ_{i−1}, S_{i−1}, r) und den Konfigurationen (Γ_{0}, S_{0}) = (Γ, S) und den Berechnungen unify T_{i} ⇝ (Γ_{i}, S_{i}). Durch Benutzung von Lemma 4.2.6 der Transitivität der Ordnung ≥ auf Konfigurationen und der Definition der Lösung des Unifikationproblems erhalten wir die Gleichungen S_{n}τ′_{i} = S_{n}τ̃_{i} für i ∈ {1, …, n} also S_{n}τ_{1} = S_{n}τ_{2}. Für das Ergebnis der Berechnung (Γ′, S′) =^{def} (Γ_{n}, S_{n}) haben wir dann Aussage 1 (a) aus der Annahme gefolgert. Um Aussage (2) zu zeigen wenden wir die Induktionshypothese auf unify an. Für die Anwendbarkeit der Induktionshypothese haben wir die Beziehung |T_{i}| < |T | (3) zu zeigen.

i=1 Wegen der Initialisierung S_{0} = S (1) ist die dritte und vierte Komponente des Maß es auf den Typisierungszuständeverringert relativ zu T , das ist die Aussage von (3) .

i Hier haben wir zwei Fälle zu untersuchen. Zuerst sei angenommen S_{i} = S, dann können wir mit obiger Argumentation die Aussage (3) herleiten. Wenn die Ungleichung S_{i} ≠ S gilt, dann folgt daraus eine Erweiterung des Abbildungsbereichs der neuen Substitution dom(S_{i}) ⊃ dom(S) und dies wirkt sich wiederum auf das Maß der freien Variablen aus V ar(T_{i}) ⊂ V ar(T ). Also wurde die erste Komponente der Maß es auf Typisierungszuständeverringert □.

1(b) Für Aussage 1(b) benutzen wir die Tatsache, daß die Konfiguration (Γ′′, S′′) eine Lösung des Unifikationproblems ist, also gelten die Gleichungen S′′τ′_{i} = S′′τ̃_{i} für die Indizes i ∈ {1, …, n}. Aus obiger Argumentation folgt die Rechtfertigung für die Benutzung der Induktionshypothese, damit erhalten wir die Abschätzungen (Γ_{i}, S_{i}) ≥ (Γ′′, S′′) also auch (Γ_{n}, S_{n}) ≥ (Γ′′, S′′) damit gilt (Γ′, S′) ≥ (Γ′′, S′′) □.

Sτ_{1} = α, Sτ_{1} = τ Wir Benutzen die Konfiguration (Γ_{1}, S_{1}) = (Γ\Γ_{α}, [τ/α]∘S) in der die Bindung der Typvariable α durchgeführt wurde und die Einschränkungen auf α aus der Typothese entfernt wurden. Nun muß gezeigt werden, daß der Algorithmus eine Normalisierung für diese Einschränkungen Γ_{α} berechnet. Die Bindung führt zu der Gleichung S_{1}τ_{1} = S_{1}τ_{2} und der Abschätzung S ≤ S_{1}. Desweiteren definieren wir einen neuen Typisierungszustandder den folgenden Berechnenungen zu Grunde liegt, durch Einsetzung der neuen Konfiguration in den alten TypisierungszustandT′ =^{def} (Γ_{1}, S_{1}) ↘ T .

Für den Beweis der Aussage 1(b) sei daran erinnert, daß die Konfiguration (Γ′′, S′′) eine Lösung des Unifikationsproblem ist, also gilt die Gleichung S′′α = S′′τ. Nun folgt aus der Abschätzung S ≤ S′′ die Abschätzung S_{1} ≤ S′′ mit Bindung von α. Aus der Beziehung Γ_{1} ⊆ Γ folgt die Implikation der Herleitungen S′′Γ′′ ⊢ S′′Γ ⇒ S′′Γ′′ ⊢ S′′Γ_{1} dies erfüllt die Definition der Abschätzung auf Konfigurationen, also gilt (Γ′′, S′′) ≤ (Γ_{1}S_{1}) (4) .

Im folgenden wird die Menge der Einschränkungen Γ_{α} auf die Typvariable α untersucht :

Γα = ∅ Falls also die Typvariable α nicht eingeschränkt ist gilt die Gleichung Γ_{1} = Γ und für die Definition (Γ′, S′) =^{def} (Γ_{1}, S_{1}) erhalten wir die Aussage 1(a) mit er Aussage (4) erhalten wir die Rechtfertigung für 1(b).

Γα ≠ ∅ Wegen der Bindung der Typvariablen α haben wir α ∈ dom(S_{1}) = dom([τ/α]∘S) woraus für die Menge der freien Variablen in dem Typisierungszustandfolgt α ∉ V ar(T′). Es gilt also die Implikation V ar(T′) ⊂ var(T ) ⇒ |T′| < |T | (5) wegen der Verminderung der ersten Komponente des Maß es auf Typisierungszustände. Als nächstes untersuchen wir die Fälle für den Typ τ der an die Typvariable α gebunden wurde, und die Einschränkung r′ = o : α → τ′ ∈ Γ_{α} welche die Argumente beim Aufruf der Funktion mkinst bilden. Wir haben als Beweisverpflichtung zu zeigen, daß mkinst eine Lösung des Einschränkungsproblems (r′)(Γ_{1}, S_{1}) berechnet; das ist die Aussage 2(a) :

τ = β Wir müssen eine Lösungskonfiguration (Γ′, S′) für das Einschränkungsproblem (r′)(Γ_{1}, S_{1}) definieren. Danach wenden wir den Fall (Var) der Charakterisierung von Lemma Lemma 4.2.4 an um die Normalisierungsbeziehung S′Γ′ ⊢ S′r′ zu zeigen. Es gibt zwei Fälle zu untersuchen : ∄o : β → τ′′ ∈ S_{1}Γ_{1} Das heißt die betrachtete Einschränkung

kann konfliktfrei in die Typothese eingefügt werden.

2(a) Sei Γ′ =^{def} (Γ_{1}, o : β → S_{1}τ′) und S′ =^{def} S_{1} dann erhalten wir o : S′(α → τ′) = S′r′ ∈ S′Γ′ ⟹ S′Γ′ ⊢ S′r′ das ist Aussage 2(a).

2(b) Unter Beachtung der Elementbeziehung r′ ∈ Γ der Herleitungsbeziehung S′′Γ′′ ⊢ S′′Γ und er der Abschätzung S′ ≤ S′′ erhalten wir durch Benutzung der Aussage (4) die erweiterte Herleitungsbeziehung S′′Γ′′ ⊢ S′′Γ′ damit ist die Abschätzung (Γ′′, S′′) ≤ (Γ′, S′) erfüllt.

∃o : β → τ′′ ∈ S_{1}Γ_{1} In diesem Fall hat der Algorithmus die Aufgabe den Konflikt zwischen der Einschränkung r′ und der bereits in der Typothese vorhandenen Einschränkung o : β → τ′′ aufzulösen. Dazu werden die Typen der beiden Einschränkungen unifiziert. 2(a) Sei T′′ = (τ′, τ′′, S_{1}, Γ_{1}, r′) ein neuer Typisierungszustandfür die Berechnung unifyT′′ ⇝ (Γ′, S′) , dann ist durch die Abschätzung (5) gerechtfertigt, die Induktionshypothese für den Aufruf der Funktion unify zu benutzen. Das Ergebnis dieser Unifikation ist die Gültigkeit der Gleichung o : S′(α → τ′) = o : S′(β → τ′′) ∈ S′Γ′, also gilt natürlich die Herleitung S′Γ′ ⊢ S′r′.

2(b) Mit der Annahme, daß die Konfiguration (Γ′′, S′′) eine Lösung für das Einschränkungsproblem (r′)(Γ_{1}, S_{1}) ist, erhalten wir per Definition die Normalisierungsbeziehung S′′Γ′′ ⊢ S′′r′ und die Abschätzung der Konfigurationen (Γ′′, S′′) ≤ (Γ_{1}, S_{1}). Anwendung der Falls (Var) aus dem Lemma 4.2.4 gibt die Gleichung S′′α → τ′ = S′′β → τ′′. Also ist (Γ′, S′) die allgemeinste Konfiguration die das Unifikationsproblem (α → τ′, β → τ′′)(Γ_{1}, S_{1}) löst die Nutzung der Aussage 1(b) in diesem Fall gibt die gesuchte Abschätzung (Γ′′, S′′) ≤ (Γ′, S′).

τ = T \overline{τ} Hier haben wir die Eigenschaften der Funktion doinst zu zeigen. Die Funktion doinst führt einen Schritt in dem Erfüllbarkeitstest für Einschränkungen aus, da für die gebundene Einschränkung r′ = o : α → τ′ ∈ Γ_{α} die Instanzdeklaration o : σ_{T} gefunden wurde. Nun ist zu prüfen ob die Einschränkungen C, die sich aus der Struktur des Instanztyps struc(σ_{T} , Γ, S) ↦ (p, T α_{p(1)} … α_{(n)} → τ, C) ergeben, auch erfüllbar sind. 3(a) Wir müssen zeigen, daß die Funktion doinst eine Nor-

malisierung für die Einschränkung r′ berechnet das sind formal der Nachweis der Berechnung doinst T′ ⇝ (Γ′, S′) der Normalisierungsbeziehung Γ′ ⊢ S′r′ und der Abschätzung mit der Resultatskonfiguration (Γ′, S′) ≤ (Γ_{1}, S_{1}). Dies wird durchgeführt indem untersucht wird, daß die Berechnung der Funktion doinst die Aussagen des Falls (Konstruktor) von Lemma 4.2.4 zusichert, wobei wir die Sequenz der Typargumente \overline{τ} = τ′_{1} … τ′_{n}, die Instanzdeklaration o : σ_{T} ∈ Γ_{1} und die Struktur des Instanztyps σ_{T} = ∀α_{1}.π_{α_{1}} ⇒ … ∀α_{n}.π_{α_{n}} ⇒ T α_{p(1)} … α_{p(n)} → τ′′ untersuchen. Bei Betrachtung des Codes der Funktion doinst ist festzustellen, daß der Aufruf doinst T′ die folgende Funktionsaufrufe auslöst. Für die Indizes i ∈ {1, …, n} ist also folgendes zu beweisen :

doinst (i, p, C_{i}, α)(Γ′_{i−1}, S′_{i−1}) ⇝ (Γ′_{i}, S′_{i})
wobei fold mkinst (Γ′_{i−1}, S′′_{i})π_{α_{i}} ⇝ (Γ′_{i}, S′_{i}) (6)
C_{i} = π_{α_{n−i−1}} … π_{α_{n}}
S′′_{i} = [S′_{i−1}α ↓ p(i)/α_{i}] ∘ S′_{i−1} (7)
(Γ′_{0}, S′_{0}) = (Γ_{1}, S_{1})

Die Aufrufe von doinst sind durch die Struktur des Instanztyps gesteuert. Es werden der Reihe nach für jede der quantifizierten Typvariablen α_{i} die Normalisierung der zugehörigen Einschränkungen durchgeführt. Dabei schrumpft die Sequenz der verbliebenen Einschränkungen C_{i} und die Argumente \overline{τ} des Typkonstruktors T werden in der Substitution S′′_{i} und die Typvariablen α_{i} gebunden. Bei dieser Bindung ist darauf zu achten, daß durch die Permutation p das entsprechende Typargument p(i) ausgewählt wird und statt dem ursprünglichen Typ T \overline{τ} die Auswahl auf dem Typ ausgeführt wie er sich zu dem Berechnungszeitpunkt darstellt, also auf dem Typ S′_{i−1}α. Dies führt zu dem komplexen Ausdruck S′′_{i} = [S′_{i−1}α ↓ p(i)/α_{i}] ∘ S′_{i−1} (7) für die Fortführung des Substitutionsparameters. Im folgenden nehmen wir die Korrektheit der Funktion mkinst an bei dem Aufruf (6) an, daraus erhalten wir die Normalisierungsbeziehungen S′_{i}Γ′_{i} ⊢ S′_{i}π_{α_{1}} … π_{α_{i}}. Wenn wir den Index i auf n setzen erhalten wir endlich die Normalisierungsbeziehung S′_{n}Γ′_{n} ⊢ S′_{n}C_{0}. Die Fortführungsoperation (7) für die Substitution in dem Typisierungszustandgibt uns die Abschätzung S′_{n} ≥ {τ′_{p(1)}/α_{1}, …, τ′_{p(n)}/α_{n}}. Um schließlich die Normalisierungsbeziehung S′Γ′ ⊢ S′(o : α → τ′) zu beweisen benötigen wir, daß dei Konfiguration (Γ′, S′) eine Lösung des Unifikationsproblems (τ′, τ′′)(Γ′_{n}, S′_{n}) ist. Dabei ist τ′′ der Resultatstyp des Körpers des Instanztyps σ_{T}. Dieser Beweis wir dadurch geführt, daß die Anwendbarkeit der Induktionshypothese auf den Typisierungszustandzu dem Unifikationsproblem gezeigt wird. Für den TypisierungszustandT′′ = (τ′, τ′′, Γ′_{n}, S′_{n}, r′) erhalten wir folgende Beziehungen unter Mengen der freien Variablen V ar(T′′) ⊆ V ar(T′) ⊂ V ar(T ) daraus folgt die Abschätzung auf dem Maß für Typisierungszustände|T′′| < |T′| (8) das erlaubt uns die Induktionshypothese anzuwenden. So erhalten wir die Aussage 3(a) aus der Berrechnung unify T′′ ⇝ (Γ′, S′).

Für den Beweis der (einzigen noch offenen) Aussage (6) müssen wir die Gültigkeit von Aussage 2(a) nachweisen. Wir führen dies aus indem wir eine Reihe von TypisierungszuständeT_{i} = (τ_{1}, τ_{2}, Γ′_{i−1}, S′_{i}, r′′) definieren, wobei die Einschränkungen r′′ ∈ π_{α_{i}} aus der Struktur des Instanztyps entnommen sind. Wir zeigen nun für die Indizes i ∈ {1, …, n} die Abschätzung |T_{i}| < |T′| (9) . Damit ist dann die Induktionshypothese auf mkinst anwendbar. Wir weisen die Abschätzung (9) nach indem wir durch eine Vergleich der Typmaß e |S′′_{i}α_{i}| und |S_{1}α| eine Veringerung der zweiten Komponente im Maß der Typisierungszuständefeststellen. Durch ein einfaches induktives Argument läst sich die Abschätzung S′′_{i} < S_{1} zeigen, dazu sind zwei Fälle zu unterscheiden : S′′_{i}α = S_{1}α Nach der Definition des Maß |.| es auf Typen haben wir |S′′_{i−1}α ↓ p(i)| = |τ_{i}| < |T \overline{τ}| = |S_{1}α|. Durch Verminderung der zweiten Komponente in dem Maß auf Typisierungszuständeerhalten wir damit Aussage (9) . S′′_{i}α ≠ S_{1}α Durch die Bindung der Typvariable α erhalten wir für die Abbildungsbereiche der Substitutionen die Beziehung dom(S′′_{i−1}) ⊃ dom(S_{1}). Daraus folgt durch Verminderung der ersten Komponente des Maß es auf Typisierungszuständedie Aussage (9) □

3(b) Um die Aussage 3(b) zu zeigen haben wir für eine weitere Lösung (Γ′′, S′′) des Einschränkungsproblems (r′)(Γ_{1}, S_{1}) die Abschätzung (Γ′′, S′′) ≤ (Γ′, S′) nachzuweisen. Lemma 4.2.4 gibt uns die Normalisierungsbeziehung S′′Γ′′ ⊢ S′′π_{α_{i}} Durch Nutzung der Abschätzung (9) (d.h. |T_{i}| < |T′|) dürfen wir die Induktionshypothese verwenden, und erhalten durch Aussage 2(b) für die Funktion mkinst die Abschätzung (Γ′′, S′′) ≤ (Γ′_{i}, S′_{i}). Lemma 4.2.4 gibt die Gleichung S′′τ′ = S′′τ′′. Durch Nutzung der Abschätzung (8) (d.h. |T′′| < |T′|) können wir die Induktionshypothese verwenden, und erhalten durch Aussage 1(b) für die Funktion unify die gesuchte Abschätzung (Γ′′, S′′) ≤ (Γ′, S′) □.

4.3 Korrektheit und Vollständigkeit der Typinferenz

In diesem Abschnitt sind die Beweise für die Eigenschaften des Algorithmus zur Typinferenz zu finden. Wir beginnen mit der Beobachtung, daß wir uns in erster Linie mit der Transformation von Herleitungen zu beschäftigen haben. Das führt in Abschnitt 4.3.1 zu dem Resultat, daß logische Herleitungen normalisiert werden können. Die Idee der Normalisierung einer logischen Herleitung liegt in der Verwendung der Quantifikationsregeln (∀I) und (∀E). Diese Regeln führen zu mehrfachen Herleitungen für dasselbe Programm. Auf diese Beobachtung folgt ein genauerer Blick auf die Herleitungsbeziehung ⊢ angewandt auf Typothesen, welcher zu dem Begriff der generischen Instanzen führt. Der Begriff der generischen Instanzen ist der Vergleichsbegriff für die Allgemeinheitseigenschaft von Typschemen. In Abschnitt 4.3.2 charakterisieren wir den Begriff der allgemeinsten Typothese der zur Definition der erweiterten Substitution führt. Diese erweiterten Substitutionen werden in 4.3.3 benutzt, um formal eine neue Sicht auf die erweiterte Unifikation zu gewinnen. Mit einem Beweis für den Zusammenhang der beiden Begriffe erweiterte Substitution und Konfiguration können wir zeigen, daß die Funktion unify die allgemeinste erweiterte Substitution für das neu formulierte Unifikationsproblem berechnet. Der Beweis der Haupteigenschaften stützt sich auf eine Reihe von Eigenschaften der benötigten Begriffe, die Beweise dieser technischen Sätze sind in Abschnitt 4.3.4 zu finden. Die beiden Erweiterungssätze geben eine Kommutationsbeziehung zwischen erweiterten Substitutionen und der Generalisierungsfunktion. Dabei wird für den (LET) Fall die Linkserweiterung zum Nachweis der Korrektheit genutzt und die Rechtserweiterung zum Nachweis der Vollständigkeit genutzt. Diese beiden Sätze enthalten den Kern der Theorie zur Verschmelzung von Überladung und parametrischen Polymorphie. Nach einer Diskussion der Hauptresultate in 4.3.5 kann der Korrektheitsbeweis in Abschnitt 4.3.6 und der Beweis der Vollständigkeit in Abschnitt 4.3.7 gefunden werden.

4.3.1 Transformation von Herleitungen

Wir beginnen mit einer Motivation der klassischen Korrektheits- und Vollständigkeitssätze für die Typinferenz. Wir entwickeln ein algorithmisches System (siehe Abbildung 4.5) das mit dem logischen System korrespondiert. Danach möchten wir eine möglichst gut Beziehung zwischen den beiden Systemen aufbauen. Die beste Beziehung wäre eine Äquivalenz :

Γ ⊢ e : σ ⇔ Γ ⊢^{W} e : σ

Der aufmerksame Leser wird sofort eine Unsauberkeit in dieser Formel entdecken. Sei ein Typisierungsproblem (Γ, e), dann kann der Algorithmus W nur einen Typ τ aber kein Typschema σ als Ergebnis berechnen. Desweiteren gibt es im logischen System eine Vielzahl an Möglichkeiten für eine Herleitung einer Typisierung zu einem gegebenen Problem (Γ, e); im Gegensatz zu dem deterministischen Algorithmus, der nur einen Typ berrechnen kann.

Um eine zufriedenstellende theoretische Verbindung zwischen dem logischen und algorithmischen System zu erhalten, spalten wir die Äquivalenz in ihre Implikationen auf.

Die einfachere Richtung ist die Korrektheit Γ ⊢^{W} e : τ ⇒ Γ ⊢ e : τ die uns sagt, daß das Ergebniss einer Typisierungsberrechnung Sinn macht. Die Korrektheitseigenschaft sagt uns, daß das Ergebnis einer algorithmischen Typisierungsberechnung auch logisch hergeleitet werden kann. Der Korrektheitsbeweis gibt dieser Aussage eine konkrete Bedeutung, da hier eine Konstruktion vorgeführt wird, die aus einer gegebenen Berechnung Γ ⊢^{W} e : τ eine Herleitung in logischen System Γ ⊢ e : τ erzeugt. Also werden wir im folgenden über Herleitungen reden. Herleitungen sind Beweisbäume deren Knoten mit Regeln eines Systems markiert sind. Die Kanten eines Beweisbaumes sind mit Aussagen dieses Systems markiert. Die Wurzel des Baumes sei zusätzlich mit der hergeleiteten Aussage markiert. Im folgenden sei eine Herleitungen mit d : Γ ⊢ e : σ notiert im Gegensatz zu der Aussage Γ ⊢ e : σ. Wir werden nun Herleitungen d : Γ ⊢ e : σ mit strukturell induktiven Argumenten zu neuen Herleitung d′ : Γ′ ⊢ e : σ′ transformieren. Diese Transformation eines Beweisbaumes werden wir das in Kürze als Γ ⊢ e : σ ⇝ Γ′ ⊢ e : σ′ notieren.

Damit können wir den wirklichen Inhalt des Korrektheitsresultats darstellen Γ ⊢^{W} e : τ ⇝ Γ ⊢ e : τ. Das heißt statt einer Implikation zwischen Aussagen haben wir eine Transformation von Herleitungen, namlich von einer Berechnung einer Typisierung zu einer logischen Herleitung einer Typisierung.

Die komplizierte Richtung der Äquivalenz ist die Eigenschaft der Vollständigkeit, die folgendes Aussehen haben sollte Γ ⊢ e : σ ⇒ Γ ⊢^{W} e : σ. Aber diese Formulierung trifft nicht den Kern, wir benötigen den Begriff der generischen Instanz eines Typschemas. Dieser Begriff ist eine Beziehung zwischen Typschemen σ und σ′. Dessen Idee kann durch Transformationen von logischen Herleitungen charakterisiert werden als ∀e.Γ ⊢ e : σ ⇝ Γ ⊢ e : σ′. Das heißt für ein Typschema σ, welches Ergebnis einer Herleitung unter den Voraussetzungen der Typothese Γ ist, daß seine generischen Instanzen σ′ auch logisch hergeleitet werden können für das selbe Typisierungsproblem. Also ist das Typschema σ allgemeiner als seine generischen Instanzen. Wir benötigen eine Funktion gen zur Formulierung des Vollständigkeitsresultats.

Sei eine Herleitung d : Γ ⊢ e : σ gegeben, dann kann eine Berechnung Γ ⊢^{W} e : τ konstruiert werden, so daß das Typschema σ eine generische Instanz des Typschemas σ′ = gen(Γ, τ) ist.

Nun hängt das Ergebnis τ des Algorithmus W nur von dem Typisierungsproblem Γ, e ab und nicht von dem Typschema σ, also folgt aus der Aussage, daß σ′ derallgemeinste Typ zu dem Problem ist. Der Kern dieser Betrachtung ist, daß wir eine Herleitung haben, welche benutzt werden kann, um jede mögliche logische Herleitung zu dem Problem zu konstruieren. Wir formalisieren nun diese Idee :

Vollständigkeit: Wenn es eine Lösung im logischen System zu dem Typisierungsproblem (Γ, e) gibt, dann berechnen wir eine Herleitung d : Γ ⊢ e : σ′, so daß für jede weitere Lösung die Transformationsbeziehung Γ ⊢ e : σ′ ⇝ Γ ⊢ e : σ gilt.

Zum Schluß wollen wir noch einen Blick auf eine Transformation von Herleitungen werfen, die in den folgenden Beweisen benutzt wird. Angenommen die Herleitung d : Γ ⊢ e : σ sei gegeben. Wenn wir Regeln des logischen Systems anwenden können, um eine Tranformation Γ ⊢ e : σ ⇝ Γ ⊢ e : σ′ zu erhalten, dann können nur die Regeln (∀I) und (∀E) neu angewendet worden sein, da der Term e konstant bleibt und die übrigen Regeln nur auf der Struktur des Terms arbeiten.

Sei eine Menge von Einschränkungen C gegeben, dann erhalten wir die Transformation Γ ⊢ e : σ ⇝ Γ.C ⊢ e : σ, wobei wir nur beobachten müssen, daß die Nebenbedingungen für Regel (∀I) nicht verletzt werden können. Die Nebenbedingungen sind für Typvariablen formuliert, welche in der Aussage Γ ⊢ e : σ bereits gebunden oder verbraucht sind, also können sie nicht mit den Typvariablen der Menge C in Konflikt kommen.

Normalisierte Herleitungen

Sie die folgende Herleitung d für die Aussage Γ ⊢ e : σ gegeben, wobei das Typschema σ durch eine Bindung der Typvariable α ensteht; d.h. σ = [τ/α]σ′

(∀E)  \frac{(∀I)  \frac{\begin{matrix}⋮ d′ \\ Γ.π_{α} ⊢ e : σ′ & α ∉ tv(Γ) \end{matrix}}{Γ ⊢ e : ∀α.π_{α} ⇒ σ′}  Γ ⊢ [τ/α]π_{α}}{Γ ⊢ e : [τ/α]σ′}

Wir möchten diese Herleitung reduzieren, so daß die Benutzung des Regelpaares (∀I)(∀E) am Ende der Herleitung entfernt wird. Um dieses zu erreichen wenden wir die Substitution [τ/α] auf die Herleitung d′ an. Also erhalten wir eine neue Herleitung d_{1} : [τ/α]Γ.π_{a} ⊢ e[τ/α]σ′ das ist eigentlich d_{1} : Γ.[τ/α]π_{α} ⊢ e : σ wegen der Nebenbedingung α ∉ tv(Γ). Nun können wir jede Verwendung einer (T AUT) Regel für eine Einschränkung o : τ′ ∈ [τ/α]π_{α} in der Herleitung d_{1} durch eine Normalisierungherleitung Γ ⊢ o : τ′ ersetzen. Diese Normalisierungsherleitungen können der rechten Premisse Γ ⊢ [τ/α]π_{α} der Regelanwendung von (∀E) in der Herleitung d entnommen werden. Wenn diese Ersetzungen für alle Einschränkungen der Menge [τ/α]π_{α} vorgenommen werden erhalten wir aus d_{1} eine neue Herleitung d_{2} : Γ ⊢ e : σ. Diese Form der Herleitungstransformation wird (∀I)(∀E)-Elimination genannt.

Sei ein Ausdruck e gegeben der nicht eine Termvariable x ist mit einem Typ τ und einer Herleitung d : Γ ⊢ e : τ, dann können wir die Herleitung so tranformieren, daß die letzte angewendete Regel zu dem Ausdruck korrespondiert ( also für die Abstraktion e = λx.e′ sollte die letzte angewante Regel (→ I) sein; oder zu der Applikation e = e′e′′ korrespondiert die Regel (→ E) usw.). Wir nennen die neue Herleitung wurzelnormalisierte Herleitung für die Aussage Γ ⊢ e : τ. Wenn diese Bedingung für jede Kante Γ′ ⊢ e′ : τ′ e′ ≠ x gilt, dann nennen wir die Herleitung normalisiert.

Jede Herleitung d kann durch Nutzung der (∀I)(∀E)-Elimination normalisiert werden. Denn jede Herleitung einer Aussage Γ ⊢ e : τ muss die Form einer wurzelnormalisierten Herleitung d′ : Γ′ ⊢ e : τ′ haben, die von Anwendungen der Regeln (∀I) und (∀E) gefolgt wird. Durch Anwendung der (∀I)(∀E)-Elimination erhalten wir eine wurzelnormalisierte Herleitung für die Aussage Γ ⊢ e : τ. Durch eine einfache strukturelle Induktion auf die vorgegebene Herleitung erhalten wir eine normalisierte Herleitung für dieselbe Aussage.

4.3.2 Die Allgemeinheitsrelation auf Typothesen und Typschemata

Als erstes untersuchen wir die Folgerungsbeziehung ⊢ auf Typothesen. Wir definieren die Abschätzung auf Typothesen Γ ≤ Γ′ gdw. (∀x : σ ∈ Γ′ ⇒ Γ ⊢ x : σ) also wenn die Herleitbarkeitsbeziehung Γ ⊢ Γ′ zwischen den Typothesen gilt. Wenn die Abschätzung Γ ≤ Γ′ gilt, dann folgt auch die Transformationsbeziehung zwischen Herleitungen (∀e.Γ′ ⊢ e : σ ⇝ Γ ⊢ e : σ) wenn die Nebenbedingung (∀o : σ_{T} ∈ Γ.∃o : σ′_{T} ∈ Γ′(Invarianz der Instanzdeklarationen)) gilt. Diese Transformation zwischen Herleitungen ist möglich, weil in einer gegebenen Herleitung Γ′ ⊢ e : σ alle Anwendungen der Regel (T AUT) für eine Termvariable x : σ ∈ Γ′ durch eine Herleitung Γ ⊢ x : σ ersetzt werden kann. Aus dieser Beobachtung folgt auch die Namensprägung Allgemeinheitsrelation für die Abschätzung auf Typothesen. Die Nebenbedingung der Regel (INST) ist durch die Invarianz der Instanzdeklarationen gewährleistet und die Nebenbedingung der (∀I) kann wie oben durch Umbenennung der gebunden Typvariablen erreicht werden.

Was ist nun eine Herleitung für eine Variablentypisierung Γ ⊢ x : σ ? Die Regeln (→ I)(→ E)(LET)(INST) sind nicht anwendbar, da die Variable x keine Termstruktur hat. Die Regel (T AUT) muß für die Termvariable x angewendet werden, also muß die Elementbeziehung x : σ′ ∈ Γ für ein Typschema σ′ gelten. Nach der (T AUT) Regel können alle Regeln angewandt welche auf der Struktur des Typschemas σ′ nutzbar sind. Die Regel (SET) wird nur dann angewandt, wenn die Konklusion dieser Regel als rechte Prämisse Γ′ ⊢ Sπ_{α} der Regel (∀E) benutzt wurde. Sei die Menge der Einschränkungen Sπ_{α} = {o_{i} : Sα → τ_{i}} und die Typothese Γ mit der Struktur Γ = T.C gegeben (wobei T die Menge aller Deklarationen x : σ ∈ Γ ist und C die Menge aller Einschränkungen o : α → τ ∈ Γ der Typothese sei), dann können die Prämissen der Regel (SET) mit Nutzung der Regel (T AUT) auf Einschränkungen aus der Menge C oder als Konklusion einer (∀E) gebildet werden. Diese Struktur für die Herleitung der Typisierung einer Termvariable ist nur eine andere Sichtweise der Charakterisierung aus Lemma 4.2.4. Die Untersuchung dieser Herleitung wird in dem Begriff der generischen Instanz eines Typschemas zusammengefaßt.

Definition. (generische Instanzen)

σ′ ≤_{Γ}^{g} σ gdw für neues u Γ, u : σ′ ⊢ u : σ gdw für neues u Γ, u : σ′ ⊢^{g}u : σ

wobei die Herleitungsbeziehung ⊢^{g} definiert ist durch die Regeln (T AUT)(∀I)(∀E) und der zusätzlichen Regel

(SET)^{SC} \frac{Γ ⊢^{g}o_{1} : τ_{1} … Γ ⊢^{g}o_{n} : τ_{n}}{Γ ⊢^{g}o_{1} : τ_{1} … o_{n} : τ_{n}}

Mit obigen Allgemeinheitsbegriff auf Typschemata können wir den Allgemeinheitsbegriff auf Typothesen charakterisieren.

Definition. Wir definieren, daß die Typothese Γ allgemeiner ist als die Typothese Γ′, kurz geschrieben Γ ≤ Γ′ wenn die folgenden äquivalenten Bedingungen erfüllt sind :

• ∀x : σ ∈ Γ′ ⇒ Γ ⊢ x : σ das heiß t Γ ⊢ Γ′.

• ∀x : σ ∈ Γ′ ⇒ x : σ′ ∈ Γ ∧ σ′ ≤_{Γ}^{g} σ das heiß t Γ ⊢^{g}Γ′.

Wenn die Eigenschaft ∀o : σ_{T} ∈ Γ.∃o : σ′_{T} ∈ Γ′ (Invarianz der Instanzdeklarationen) gilt, dann

• ∀e.Γ′ ⊢ e : σ ⇒ Γ ⊢ e : σ

Nun wollen wir aus der Struktur der Typschemata σ, σ′ auf die Struktur der Herleitung zur Abschätzung σ ≤_{Γ}^{g} σ′ schließen. Wir machen für die Strukturen der Typschemata folgende Annahmen σ = ∀.\overline{α}.C ⇒ τ und σ′ = ∀.\overline{β}.C′ ⇒ τ′. Aus diesen Annahmen ergeben sich die folgenden Daten; eine Substitution S mit Abbildungsbereich dom(S) ⊂ \{\overline{α}\} und der Gleichung Sτ = τ′, desweiteren soll die Normalisierungsbeziehung Γ, C′ ⊢ SC für die Einschränkungsmenge SC gelten. Also hat die Herleitung der benötigten Aussage Γ, u : σ ⊢ u : σ′ folgende Normalform. Zuerst wird die Regel (T AUT) für die Termvariable u angewendet. Danach werden die Quantoren eliminiert, also für jede Typvariable α der Sequenz \overline{α} wird die Regel (∀E) angewandt, wobei die rechten Prämissen aus der Normalisierungsbeziehung Γ, C′ ⊢ SC gebildet werden. So erhalten wir eine Herleitung für die Aussage Γ, C′, u : σ ⊢ u : τ′. Auf diese Herleitung wenden wir die Regel (∀I) für jede Typvariable β der Sequenz \overline{β} an, bis wir eine Herleitung für die Aussage Γ, u : σ ⊢ u : σ′ konstruiert haben. Als Nebenbedingung für die Konstruktion benötigen wir \{\overline{β}\} ∩ (tv(Γ) ∪ fv(σ)) = ∅, diese Bedingung kann problemlos durch Umbenennung der gebundenen\overline{β} erreicht werden. Hier werden noch zwei Sonderfälle der generischen Instanzbeziehung ausgeführt. Die generische Instanzbeziehung eingeschränkt auf Typen ist die Gleichheit, also τ ≤_{Γ}^{g} τ′ gdw τ = τ′ weil der Typ τ keine gebundenen Typvariablen hat also ist nach obiger Charakterisierung die einzig mögliche Substitution die Identität. Alle Instanzen eines Typs besitzen den selben Typkörper und quantifizieren keine freien Typvariablen, also τ ≤_{Γ}^{g} σ gdw σ = ∀\overline{α}.C ⇒ τ wobei für die quantifizierten Typvariablen \{\overline{α}\} ∩ tv(τ) = ∅ gilt, der Beweis wird genauso mit obiger Argumentation geführt.

Eingeschränkte Typschemata

Definition. (schwache generische Instanzen und eingeschränkte Typschemata)

Im folgenden nennen wir ein Tupel (C, σ) ein eingeschränktes Typschema das aus einer Menge von Einschränkungen C und einem Typschema σ besteht. Auf eingeschränkten Typschemata definieren wir die schwache Instanzbeziehung (C, σ) ≤_{T}^{w} (C′, σ′) durch den reflexiven transitiven Abschluß, der syntaktisch von folgenden Regeln induziert wird :

\begin{matrix}(∀L) & \frac{π_{α} ⊆ π′_{α} α ∉ tv(T.C, σ)}{(C.π_{α}, σ) ≤_{T}^{w} (C, ∀α.π′_{α} ⇒ σ)} \\ (∀R) & \frac{T.C ⊢ [τ/α]π_{α}}{(C, ∀α.π_{α} ⇒ σ) ≤_{T}^{w} (C, [τ/α]σ)} \end{matrix}

Man beachte, daß dieser Beziehungsbegriff sehr natürlich zu einer Transformation von Herleitungen führt.

(C, σ) ≤_{T}^{w} (C′, σ′) ⟹ T.C ⊢ e : σ ⇝ T.C′ ⊢ e : σ′

Dieses Gesetz ist einfach zu sehen durch Untersuchung der Herleitung einer Abschätzung (C, σ) ≤_{T}^{w} (C′, σ′). Die Reflexivität und Transitivität der Transformationsbeziehung ≤_{T}^{w} auf Herleitungen ist offensichtlich. Ansonsten läßt sich immer die Regel (∀I) auf eine Herleitung anwenden wenn für die Abschätzung die Regel (∀L) benutzt wurde; genauso läßt sich immer die Regel (∀E) auf eine Herleitung anwenden wenn die Regeln (∀R) für die Abschätzung benutzt wurde. Diese Konstruktion funktioniert wegen der Nebenbedingung α ∉ tv(T.C, σ) in der Regel (∀L). So wird die Herleitung einer schwachen generischen Instanzbeziehung zur Konstruktion einer Beweistransformation einer Typisierung benutzt.

Wir können noch eine weitere Transformation auf Herleitungen konstruieren.

(C, σ) ≤_{T}^{w} (C′, σ′) ⟹ T.C′.u : σ′ ⊢ e : σ′′ ⇝ T.C.u : σ ⊢ e : σ′′

Man beachte die Kontravarianz bei der Nutzung der eingeschränkten Typschemata, d.h. die Ordnung der zwei eingeschränkten Typschemata kehrt sich bei ihrer Benutzung in der Herleitungstransformation um. Wir nennen deshalb im folgenden das erste Gesetz Kovarianzgesetz und das zweite Gesetz Kontravarianzgesetz für schwache generische Instanzen. Beweis: Die Gültigkeit der schwachen generischen Instanzbeziehung erlaubt die Nutzung des Kovarianzgesetzes, so können wir die Herleitung (T AUT) T.C.u : σ ⊢ u : σ zu einer Herleitung T.C′.u : σ ⊢ u : σ′ (1) transformieren. Wir transformieren nun die gegebene Herleitung T.C′.u : σ′ ⊢ e : σ′′ indem wir jede Nutzung der Regel (T AUT) für die Termvariable u also Herleitungen (T AUT) T.C′.u : σ′ ⊢ u : σ′ durch die Herleitung (1) ersetzen, dadurch erhalten wir die neue Herleitung T.C′.u : σ ⊢ e : σ′′ (2) .

Durch ein einfaches induktives Argument über die Nutzung der Regel (∀L) in der Herleitung einer Abschätzung (C, σ) ≤_{T}^{w} (C′, σ′) die Teilmengenbeziehung C′ ⊆ C auf den Mengen von Einschränkungen und für die Menge von Typvariablen V =^{def} tv(C) \ tv(T.C′) erhalten wir die Mengengleichung C′ = C \ C_{V} wobei die Menge C_{V} die Menge aller Einschränkung aus C auf die Typvariablen aus V ist. Wenn wir also die Herleitung (2) nehmen und überall die Mengen von Einschränkungen C′ durch C ersetzen, werden die Nebenbedingungen der Regel (∀I) nicht verletzt :

∀α ∈ tv(T.C′). α ∉ tv(C′ \ C′_{α}) ⟹ α ∉ tv(C \ C_{α})

Also transformieren wir die Herleitung (2) zur Herleitung T.C.u : σ ⊢ e : σ′′ □

Wir haben wieder ähnlich wie bei der generische Instanzbeziehung, daß eine Einschränkung der schwachen generischen Instanzbeziehung auf Typen zur Gleichheitsbeziehung führt. Formal haben wir die Implikation (C, τ) ≤_{T}^{w} (C′, τ′) ⇒ τ = τ′. Dies ist leicht gezeigt indem wir bemerken, daß die einzige anwendbare Regel auf der rechten Seite ist (∀L) aber die Nebenbedingung verbietet die Quantifikation einer Typvariablen α ∈ tv(τ). Also kann eine darauffolgende Anwendung der Regel (∀R) nicht den Typ τ ändern.

Die Generalisierungsfunktion

Definition. (Generalisierungsfunktion gen)

gen(T.C, σ) =^{def} (C \ C\overline{α}, ∀\overline{α}.C\overline{α} ⇒ σ)

wobei \overline{α} eine maximale Sequenz von Typvariablen ist \overline{α} = α_{1} ⋯ α_{n}, so daß sie der reihe nach durch die (∀I) quantifiziert werden könnten, also α_{i} ∉ tv(T.C\{α_{1} ⋯ α_{i}}) und α_{i} ∈ tv(σ). Weiter Sie die Funktion g(Γ, σ) definiert durch Anwendung der Funktion gen wobei nur das berechnete Typschema zu dem Ergebnis zählt, Durch diese Definition erhalten wir folgende Eigenschaften :

(gen1) Wenn gen(Γ, σ) = (Γ′, σ′) dann ∀e.Γ ⊢ e : σ ⇝ Γ′ ⊢ e : σ′ durch Anwendung der Regel(∀I).

(gen2) Wenn g(Γ, σ) = σ′ dann ∀e.Γ ⊢ e : σ ⇝ Γ ⊢ e : σ′. Dies ist leicht zu sehen, indem man erst obige Transformation Γ ⊢ e : σ ⇝ Γ′ ⊢ e : σ′ benutzt. Damit läßt sich die Menge von Einschränkungen C = Γ\Γ′ definieren, durch die bei Anwendung der Regel (∀I) verbrauchten Einschränkungen. Wir können aber die Herleitung einfach um die Menge C erweitern Γ′ ⊢ e : σ′ ⇝ Γ′.C = Γ ⊢ e : σ′ und erhalten so die gesuchte Herleitung.

(gen3) Wenn gen(Γ, σ) = (Γ′, σ′) dann ∀α ∉ tv(σ).Γ_{α} = Γ′_{α}, wegen der Nebenbedingung α_{i} ∈ tv(σ).

(gen4) gen(T.C.π_{α}, σ) = gen(T.C, ∀α.π_{α} ⇒ σ) für α ∉ tv(T.C) und α ∈ tv(σ).

(gen5) Wegen der Maximalität erhalten wir für gen(T.C, σ) = (T.C′, σ′) daß die Implikation ∀α ∈ tv(σ)gilt.α ∉ tv(T.C′ \ α) ⇒ C′_{α} = ∅.

(gen6) gen(Γ, σ) = (Γ′, σ′) ⇒ gen(Γ.π_{α}, σ) = (Γ′.π_{α}, σ′) wenn α ∉ tv(σ).

Unter Nutzung der Eigenschaft (gen6) erhalten wir ein ein Gesetz für Transformationen von Berechnungen welche die Funktion gen an Stelle von Quantifikationsregeln benutzen.

T.C ⊢^{W,d} e : τ ⇝ T.C.C′ ⊢^{W,d} e : τ

Nehmen wir an, daß die Typvariablen der Menge von Einschränkungen C′ nicht in Konflikt geraten mit den Typvariablen die durch die Funktion gen quantifiziert werden in der Berechnung der AussageT.C ⊢^{W,d} e : τ. Wir benutzen dann die Eigenschaft (gen6) damit jede Regelanwendung von (LET)^{W,d} weiterhin zulässig ist bei Erweiterung der Einschränkungsmenge um C′. Keine Nebenbedingungen der Typsysteme W, d werden durch die Erweiterung der der Menge von Einschränkungen verletzt, also ist das Gesetz gültig.

4.3.3 Eingeschränkte Substitution

Nun wollen wir der Frage nach dem Inhalt der Funktion unify stellen. In dem Hindley/Milner System (also unserem ohne Überladung) werden beim Beweis der Korrektheit Substitutionen auf Herleitungen zur Typisierung angewendet. Es handelt sich dabei um Anwendung der Implikation (Γ ⊢^{HM} e : σ ⇒ SΓ ⊢^{HM} e : Sσ). Mit einem Blick auf das System O kann man sich überzeugen, daß dieses Gesetz auch in System O gilt. Aber in einem System mit Einschränkungen machen Substitutionen nur Sinn, wenn Sie auch erfüllbar sind. Also muß der der Algorithmus zur Typinferenz auch prüfen ob alle Instantiierungen die im Programm auftreten auch erfüllbar sind.

Sei eine Typothese Γ und eine Einschränkung o : α → τ ∈ Γgegeben. Wenn für einen Typkonstruktor T keine Instanzdeklaration o : σ_{T} ∈ Γ in der Typothese existiert, dann führt eine Substitution S mit Sα = T \overline{τ} bei Anwendung auf die Typothese SΓ zu einem Widerspruch. Denn die Einschränkung o : T \overline{τ} → Sτ macht keinen Sinn, Sie wird nicht durch eine Instanzdeklaration o : σ_{T} erfüllt. In diesem Fall ist die Implikation (Γ ⊢^{O} e : σ ⇒ SΓ ⊢^{O} e : Sσ) korrekt aber sinnlos.

Wir definieren die eingeschränkten Variablen einer Typothese Γ durch rv(Γ) =^{def} {α|o : α → τ ∈ Γ}. Eine Substitution S werde konfliktfrei mit der Typothese Γ genannt genau dann wenn die Substitution keine Einfluß auf eingeschränkte Variablen hat dom(S) ∩ rv(Γ) = ∅. Also ist jede Konfiguration (Γ, S) ein Tupel aus einer Typothese Γ und einer dazugehörigen konfliktfreien Substitution. Die Menge der determinierten Variablen einer Substitution sei definiert als dv(S) =^{def} \{α|Sα = T \overline{τ}\}. Falls nun eine Substitution auf eine Einschränkung angewendet wird, und die eingeschränkte Typvariable zu der Menge der Determinierten gehört, dann wird die Einschränkung determiniert genannt.

Als nächstes untersuchen wir wie Substitutionen bei Konflikten auf Typothesen wirken. Im folgenden nehmen wir immer an das die behandelten Typothesen normalisiert sind. Wir definieren nun, daß die Anwendung einer Substitution auf eine Typothese Γ konvergiert wenn die resultierende Typothese wieder normalisiert werden kann, das heiß t wenn alle determinierten Einschränkungen aufgelöst werden können. Formalisiert benötigen wir für eine Typothese Γ = T.C die Eigenschaft :

SΓ ↓ gdw ∃C′ ST.C \ dv(S).C′ ⊢ SC_{|dv(S)}

Die obigen Daten können kürzer notiert werden mit den Schreibweisen SΓ ↓ C′ oderSΓ ↓ Γ′ oderΓ ≤^{(S,C′)} Γ′ wobei die neue normalisierte Typothese durch Entfernen der determinierten und Einfügung der neuen Einschränkungen entsteht Γ′ = ST.C \dv(S).C′ Die Idee der der Definition von Γ′ ist die der konservativen Erweiterung der substitutierten Typothese SΓ, also die Aussage Γ′ ⊢ SΓ muß gültig sein, was offenbar von der Definition auch erfüllt wird. Wenn man die Herleitung dieser Aussage untersucht ist festzustellen, daß die Menge der Einschränkungen C′ gerade die Einschränkungen sind die bei der Herleitung in den (T AUT) Regeln neu benutzt werden. Die Menge C′ enthält genau die Einschränkungen die gebraucht werden um die determinierten Einschränkungen aufzulösen. Dual zu Obigem ist der Begriff der divergierenden Substitutionsanwendung auf eine Typothese SΓ ↑ definiert gdw eine Menge von Einschränkungen mit obiger Eigenschaft nicht existiert, zum Beispiel bei einem nicht auflösbaren Konflikt wenn eine determinierte Einschränkung o : T \overline{τ} → τ′ ∈ SΓ vorhanden ist aber keine dazu passende Instanzdeklaration o : σ_{T} ∈ Γ.

Wir fassen die obige Betrachtung nun zu einer neuen Begriffsbildung, der eingeschränkten Substitution, zusammen. Wir nennen das Tupel (S, C′) bestehend aus einer Substitution S und einer Menge von Einschränkungen C′ wobei die Substitution auf der Einschränkungsmenge nicht wirkt SC′ = C′ eine eingeschränkte Substitution und benutzen die Buchstaben U, V, W zu ihrer Benennung. Weiter sei definiert :

(S, C′)Γ ↓ gdw T.C \ dv(S).C′ ⊢ SC_{|dv(S)} für Γ = T.C

Dual sei der Begriff der divergierenden Anwendung einer eingeschränkten Substitution (S, C′) auf eine Typothese Γ definiert und notiert als (S, C′)Γ ↑ gdw S(Γ.C′) ↑. Die Charakterisierung der Menge C′ führt zu einer minimalen Menge im Konvergenzfall SΓ ↓ wobei unter Minimalität zu verstehen ist, daß jede Einschränkung r ∈ C′ in einer Regelanwendung (T AUT) genutzt wird bei der Herleitung der Normalisierungsaussage. Wir definieren den Begriff der minimalen konservativen Erweiterung der Typothese T.C bei Anwendung der Substitution S.

C′ = mce(S, T.C) gdw C′ minimal und ST.C′ ⊢ SC

Lemma 4.3.1 (Anwendung von eingeschränkten Substitutionen auf Herleitungen)

Sei eine Herleitung Γ ⊢ e : σ und eine terminierende Substitutionsanwendung (S, C′)Γ ↓ Γ′ gegeben. Dann läßt sich daraus eine Herleitung Γ′ ⊢ e : Sσ konstruieren. Falls eine Substitutionsanwendung (S, C′)Γ ↑ divergiert und die Typothese die Struktur Γ = T, C besitzt, dann gibt es keine Menge von Einschränkungen C′′, so daß sich die Aussage ST, C \ dv(S), C′′ ⊢ e : Sσ normalisiert herleiten läßt. (Das negative Resultat gilt nur in dem Fall, daß bei der Herleitung T, C ⊢ e : σ jede determinierte Einschränkung aus C durch eine Regelanwendung von (T AUT) benutzt wurde) Beweis: Offensichtlich ist SΓ ⊢ e : Sσ eine Herleitung in System O, diese Herleitung muß nun noch normalisiert werden. Dazu wird einfach in der Herleitung jede Anwendung der Regel (T AUT) auf eine determinierte Substitution r ∈ SC_{|dv(S)} durch eine Herleitung Γ′ ⊢ r ersetzt, welche sich aus der Definition einer terminierenden Substitutionsanwendung SΓ ↓ Γ′ ergibt. So erhalten wir eine Herleitung für die Aussage Γ′ ⊢ e : Sσ.

Der Beweis für die duale Aussage mit einem ähnlichen Argument wie oben geführt.

Definition. (Variablenmengen für eingeschränkte Substitutionen)

Sei U = (S, C) eine eingeschränkte Substitution, dann definieren wir folgende Variablenmengen :

codom(S) =^{def} ⋃{tv(Sα)|α ∈ dom(S)}
dom(U) =^{def}  dom(S)
dv(U) =^{def}  dv(S)
rv(U) =^{def}  rv(C)
tv(U) =^{def}  tv(C)
v(U) =^{def} dom(U) ∪ codom(U) ∪ tv(U)

Der Zusammenhang zwischen Konfigurationen und eingeschränkten Substitutionen

Nach der Untersuchung der eingeschränkten Substitutionen folgt hier die Verbindung zu dem Begriff der Konfiguration.

Lemma 4.3.2 Charakterisierung der Beziehung ≤ auf Konfigurationen durch die normalisierte Beziehung ≤^{U} auf Typothesen.

(Γ, S) ≤ (Γ′, S′) ⇔ SΓ ≤^{(R,C′′)} S′Γ′
wobei S ≤^{R} S′ und SΓ = T.C und SΓ′ = T.C′ und C′′ = R(C′ \ C)

Beweis: Die Definition der Abschätzung ≤ auf Konfigurationen gibt die Existenz einer vermittelnden Substitution R für die Abschätzung auf Substitutionen S ≤^{R} S′. Aus der Definition von Konfigurationen folgt eine konfliktfreie Anwendung der Substitution auf die Typothese, daß wir die Struktur SΓ = T.C erhalten. Das gleiche Argument gilt auch für die Struktur der Typothese S′Γ′ = RSΓ′, also können wir definieren: SΓ′ = T′.C′. Daraus folgt offensichtlich die einzige Bedingung welche für die Äquivalenz benötigt wird ist die Gleichung T = T’

Nun werfen wir einen genaueren Blick auf die Struktur der Typothese S′Γ′. Wir erhalten die Gleichungen S′Γ′ = RSΓ′ = RT.C′ = RT.RC′. Also ist C′ eine Menge von Einschränkungen die nicht durch die Substitution R determiniert werden, d.h. C′_{|dv(R)} = ∅. Daraus folgt die Mengengleichung C′ \ C = C′ \ (C \ dv(R)). Unter Benutzung der obigen Nebenbedingungen für die Äquivalenz läßt sich die Reihe von Gleichungen RC′ = R(C\dv(R).C′\C) = R(C\dv(R)).R(C′\C) = R(C\dv(R)).C′′

(1) zeigen, wobei wir in der letzten Gleichung die Definition der konservativen Erweiterung C′′ für die Auflösung der determinierten Einschränkungen benutzt haben. Mit diesem Material können wir den Beweis der Äquivalenz vervollständigen.

S′Γ′ ⊢ S′Γ
⇔ Voraussetzung S ≤^{R} S′
S′Γ′ = RSΓ′ ⊢ RSΓ
⇔ Voraussetzungen über die Struktur von SΓ′ und SΓ
S′Γ′ = RT.C′ ⊢ RT.C
⇔ wegen RT.C′ ⊢ RT mit (T AUT)
S′Γ′ = RT.C′ ⊢ RC
⇔ Zerlegung der Constraints RC′ in (1)
S′Γ′ = RT.C \ dv(R).C′′ ⊢ RC
⇔ Abschwächung auf determinierte Constraints
S′Γ′ = RT.C \ dv(R).C′′ ⊢ R(C_{|dv(R)})
⇔ Definition der Anwendung von eingeschränkten Substitutionen
(R, C′′)T.C ↓ S′Γ′
⇔ Voraussetzung über die Struktur von SΓ
(R, C′′)SΓ ↓ S′Γ′
⇔ Definition der Abschätzung von Typothesen durch eine eingeschränkte Substitution
SΓ ≤^{(R,C′′)} S′Γ′

Die Aussage dieses Beweises ist: Wenn die Deklarationen der Typothesen Γ und Γ′ übereinstimmen dann stimmt auch der Abschätzungsbegriff auf Konfigurationen mit dem Begriff der terminierenden Anwendung eingeschränkter Substitutionen auf normalisierte Typothesen überein. Ein Blick auf den Unifikationsalgorithmus aus Abschnitt 4.2.1 zeigt, daß die Berechnung die Deklarationen unverändert läßt. Nun definieren wir die Abschätzung auf eingeschränkte Substitutionen U ≤_{Γ}^{V} W gdw UΓ ↓ Γ′ ∧ V Γ′ ↓ Γ′′ ∧ W Γ ↓ Γ′′. Die Transitivität dieser Relation ≤_{Γ} ist einfach zu sehen. Desweiteren definieren wir die Komposition von eingeschränkten Substitutionen V U =^{def} W gdw U ≤_{Γ}^{V} W. Der eingeschränkte Unifikator U eines Unifikationsproblems (Γ)(τ_{1}, τ_{2}) sei definiert

als τ_{1} ≈^{U}_{Γ} τ_{2} gdw U eine Unifikator für die Typen τ_{1}, τ_{2} ist und die Anwendung auf die Typothese terminiert UΓ ↓. Der allgemeinste eingeschränkte Unifikator sei definiert als τ_{1} ∼^{U}_{Γ} τ_{2} gdw τ_{1} ≈^{U}_{Γ} τ_{2} und ∀V.τ_{1} ≈^{V}_{Γ} τ_{2} ⇒ U ≤_{Γ} V. Im folgenden nutzen wir eine Minimalitätseigenschaft um den allgemeinsten Unifikator zu charakterisieren. Wenn die eingeschränkte Substitution (S, C) ein allgemeinster eingeschränkter Unifikator für das Problem (Γ)(τ_{1}, τ_{2}) ist dann gilt die Gleichung C = mce(S, Γ), das heiß t die Menge von Einschränkungen C ist eine minimale konservative Erweiterung für die Anwendung der Substitution S auf die Typothese Γ. Nun ist die Aussage von Lemma 4.2.7, daß der Algorithmus unify die allgemeinste unifizierende Konfiguration für das Unifikationsproblem (SΓ)(τ_{1}, τ_{2}) berechnet. Durch die Charakterisierung der Beziehung ≤ auf Konfigurationen erhalten wir ein Korrolar, daß die Berechnung der allgemeinsten eingeschränkten Unifikation behandelt.

unify(τ_{1}, τ_{2})(Γ, S) = (Γ′, S′) mit S ≤^{R} S′ und C′′ = R(SΓ \ SΓ′) ⇔ τ_{1} ∼^{(R,C′′)}_{SΓ} τ_{2}

Wenn wir in obiger Berechnung als Substitution S die Identität id nehmen, können wir den Algorithmus unify zur Definition des Algorithmus mgcu benutzen :

mgcu(Γ)(τ_{1}, τ_{2}) = (R, C′′) ⇔ τ_{1} ∼^{(R,C′′)}_{Γ} τ_{2}

Man erinnere sich an die syntaktische Charakterisierung des Begriffs der generischen Instanz von Typschemen σ ≤_{Γ}^{g} σ′. Die Beziehung gilt gdw die Typschemen die Struktur σ = ∀.\overline{α}.C ⇒ τ und σ′ = ∀.\overline{β}.C′ ⇒ τ′ haben und eine Substitution S vorhanden ist mit den Eigenschaften dom(S) ⊂ \{\overline{α}\} und Sτ = τ′ und Γ, C′ ⊢ SC. Wir werden nun diese Beziehung mit dem Begriff der eingeschränkten Substitution neu entwickeln . Sei eine einfache Substitution S gegeben, die nicht mit den gebunden Typvariablen des Typschemas σ in Konflikt gerät dom(S) ⊆ bv(σ). Also können wir die Konfliktfreiheit der Substitution annehmen dom(S) ∩ tv(Γ) = ∅ das für zur der Terminierung SΓ ↓ Γ. Damit führt die Nebenbedingung Γ.C′ ⊢ SC zu einer eingeschränkten Substitution U = (S, C′) und läßt sich als Terminierungsbedingung UΓ.C ↓ ausdrücken. Also ∀.\overline{α}.C ⇒ τ ≤_{Γ}^{g} ∀.\overline{β}.C′ ⇒ τ′ gdw ∃U und U = (S, C′) und dom(U) ⊆ \{\overline{α}\} und Uτ = τ′ und UΓ.C ↓.

4.3.4 Beziehungen zwischen Aussagen

Wir haben die Abschätzungsbeziehung und die Anwendung von eingeschränkten Substitutionen auf Typothesen und auf eingeschränkte Typschemen definiert. Nun wollen wir die natürliche Erweiterung auf Herleitungen untersuchen. Wir werden im folgenden Diagramme benutzen um komplexe technische Zusammenhänge auf einem Blick darzustellen.

Zuerst definieren wir den Pfeil [figure: (σ, Γ); ≤; (σ′, Γ′)] (oder syntaktisch (σ, Γ) ≤ (σ′, Γ′) ) gdw die Deklarationen konstant bleiben, das heiß t Γ = T.C und Γ′ = T.C′, und die entsprechenden eingeschränkten Typschemen in schwacher generischer Instanzbeziehung zueinander stehen, d.h. (C, σ) ≤_{T}^{w} (C′, σ′). Wie in Abschnitt 4.3.2 erläutert kann die obige Beziehung zu einer Beziehung von Herleitungen erweitert werden bei einen konstanten Term. Sei also die Herleitung d : Γ ⊢ e : σ gegeben, dann erhalten

wir die Herleitung d′ : Γ′ ⊢ e : σ′ kurz als Pfeil notiert [figure: Γ ⊢ e : σ; ≤; Γ′ ⊢ e : σ′] .

Nun wollen wir die analoge Begriffbildung mit eingeschränkten Substitutionen ausführen. Wir definieren den Pfeil [figure: (σ, Γ); U; (σ′, Γ′)] gdw die Anwendung der Substitution auf die Typothese terminiert UΓ ↓ Γ′ und die Substitution zwischen den Typschemen vermittelt Uσ = σ′. Der Pfeilbegriff ist wieder so gewählt, daß er sich durch einen Rückblick in Abschnitt 4.3.3 auf Herleitungen mit einem konstanten Term e erweitern läßt. Sei also obiger Pfeil und die Herleitung d : Γ ⊢ e : σ gegeben, dann erhalten wir die neue Herleitung d′ : Γ′ ⊢ e : σ′ kurz eine Pfeil zwischen Herleitungen [figure: Γ ⊢ e : σ; U; Γ′ ⊢ e : σ′] .

Man erinnere sich an die Definition der Funktion gen in dem Abschnitt 2. Wir formulieren nun eine Eigenschaft der Funktion in Pfeilschreibweise. Wird definieren den Pfeil [figure: (σ, Γ); gen; (σ′, Γ′)] gdw Anfang (bzw. Ende) des Pfeils genau das Argument (bzw. Ergebnis) einer Berechnung mit gen sind also gen(Γ, σ) = (Γ′, σ′), dann besagt die Eigenschaft (gen1) die Erweiterung des Pfeils zu einer Herleitungstransformation nämlich [figure: Γ ⊢ e : σ; gen; Γ′ ⊢ e : σ′] . Wir führen noch eine Pfeilnotation

für die Anwendung der Funktion g ein [figure: (σ, Γ); g; σ′] .

Sei eine Anwendung der Funktion gen gegeben als Pfeil [figure: (τ, Γ); gen; (σ, Γ′)] und eine terminierende Anwendung einer beschränkten Substitution U auf die Ergebnistypothese Γ′ der Generalisierungsberechnung UΓ′ ↓. Wir nehmen an, daß das Typschema σ die Struktur σ = ∀\overline{α}.C′ ⇒ τ habe, dann können wir auch annehmen, daß die Substitution nicht mit den gebunden Typvariablen des Typschemas in Konflikt gerät also formal v(U) ∩ \{\overline{α}\} = ∅. Wegen den Eigenschaften der Funktion gen gelten die Gleichungen Γ\overline{α} = C′ ∧ Γ′ = Γ \ C′. Daraus folgern wir, daß die Substitutionsanwendung von U auch auf der ursprünglichen Typothese terminiert also UΓ ↓. Wir nehmen nun an, daß die eingeschränkte Substitution U die Struktur U = (S, C) hat. Aus den Eigenschaften der Funktion gen folgen die Gleichungen (UΓ)\overline{α} = S(Γ\overline{α}) = SC′. Wegen der Konfliktfreiheit der Substitution gilt auch noch die Gleichung Uσ = ∀\overline{α}.SC′ ⇒ Sτ. Wir können nun diese technisch komplexe Betrachtung in einem einfachen Kommutationslemma zusammenfassen.

Satz 4.3.3 (Linkserweiterung) Sei die Berechnung gen(τ, Γ) = (σ, Γ′) und die terminierende Substitutionsanwendung UΓ′ ↓ mit v(U) ∩ bv(σ) = ∅ gegeben, dann gilt die Kommutationsgleichung U ∘ gen(τ, Γ) = gen ∘ U(τ, Γ).

[figure: (τ, Γ); gen; U; (σ, Γ′); U; (Uτ, UΓ); gen; (Uσ, UΓ′)]

Satz 4.3.4 (Substitution auf die generische Instanzbeziehung) Sei eine generische Instanzbeziehung zwischen Typschemen σ ≤_{Γ}^{g} σ′ gegeben und terminierende Anwendung einer eingeschränkten Substitution auf die Typothese UΓ ↓, dann erhält man durch Anwendung der Substitution U auf die Abschätzung wieder eine gültige Abschätzung Uσ ≤_{UΓ}^{g} Uσ′. Beweis: Wir machen folgende Annahmen über die Struktur der benutzten Typschemata σ = ∀\overline{α}.C ⇒ τ und σ′ = ∀\overline{β}.C′ ⇒ τ′. Da das Typschema σ allgemeiner als das Typschema σ′ ist erhalten wir eine Substitution die die Bedingungen dom(S) ⊆ \{\overline{α}\} und Sτ = τ′ und Γ, C′ ⊢ SC erfüllt.

Wir nehmen nun für die Struktur der eingeschränkten Substitution die Gleichung U = (S′, C′′) an und die Konfliktfreiheit mit den quantifizierten Typvariablen v(U) ∩ \{\overline{α}, \overline{β}\} = ∅. Damit können wir die Terminierungseigenschaft erweitern U(Γ, C′) ↓ und erhalten eine erweiterte Normalisierungsbeziehung UΓ, C′ ⊢ S′SC für die Einschränkungsmenge C des allgemeineren Typschemas. Mit dieser Normalisierungsbeziehung und der offensichtlichen Gleichung S′Sτ = S′τ′ erhalten die gesuchte erweiterte Instanzbeziehung Uσ ≤_{UΓ}^{g} Uσ′.

Korrolar 4.3.5 (Anwendung von eingeschränkten Substitutionen auf syntaktische Herleitungen)

Sei eine syntaktische Herleitung Γ ⊢^{d}e : τ gegeben und eine eingeschränkte Substitution U deren Anwendung auf die Typothese terminiert UΓ ↓, dann erhält man bei Anwendung der Substitution U auf die Herleitung wieder eine normalisierte Herleitung UΓ ⊢^{d}e : Uτ. Beweis: Der Beweis wird mit struktureller Induktion über die syntaktische Herleitung geführt

Die Fälle für die Regeln (→ I)^{d}, (→ E)^{d} sind trivial durch die Benutzung der Induktionshypothese auf die Prämissen.

Für die Regel (LET)^{d} wenden wir die “Linkserweiterung” auf die mittlere Prämisse an. Sei also die letzte Regeleanwendung in der Herleitung von folgender Form :

(LET)^{d} \frac{Γ ⊢^{d}e : τ′ g(τ′, Γ) = σ Γ, u : σ ⊢^{d}e′ : τ}{Γ ⊢^{d}let u = e in e′ : τ}

Dann ist die Anwendung von U auf die linke und rechte Prämisse durch die Induktionshypothese erlaubt. Die Anwendung von U auf die mittlere Prämisse gibt die

Gleichungen : g(Uτ′, UΓ) = g ∘ U(τ′, Γ) =^{Satz 4.3.3} U ∘ g(τ′, Γ) = Uσ.

Für die Regel (T AUT)^{d} ist zu beachten, daß U natürlich auf den Prämissen wirkt.

(T AUT)^{d} \frac{x : σ ∈ Γ  σ ≤_{Γ}^{g} τ}{Γ ⊢^{d}x : τ}

Offensichtlich gilt die Elementbeziehung x : Uσ ∈ UΓ. Der Satz 4.3.4 über die Anwendung von eingeschränkten Substitutionen auf die generische Instanzbeziehung gibt uns die Abschätzung Uσ ≤_{UΓ}^{g} Uτ. Damit haben wir die Prämissen um die Regel (T AUT)^{d} anzuwenden und erhalten so die Aussage UΓ ⊢^{d}x : Uτ □.

Nun wollen wir die Möglichkeit untersuchen einen zu Satz 4.3.3 dualen Satz zu formulieren; ein Lemma zur Rechtserweiterung. Wir beginnen mit dem Tupel (τ, Γ) und einer eingeschränkten Substitution U mit Terminierungseigenschaft UΓ ↓ und fragen nach der Möglichkeit einer kommutierenden Anwendung der Funktion g und der Substitutionsanwendung von U auf das Tupel (τ, Γ). Wir beginnen also mit der einfachen Situation

[figure: (τ, Γ); g; U; σ; ?; (Uτ, UΓ); g; σ′]

Für den oberen Pfeil erhalten wir die Daten Γ = Γ′′.C′′ , σ = ∀\overline{α}.C′′ ⇒ τ , \{\overline{α}\} ∩ tv(Γ′′) = ∅. Der untere Pfeil gibt uns die Daten UΓ = UΓ′.C′ und σ′ = ∀\overline{β}.C′ ⇒ Uτ und \{\overline{β}\} ∩ tv(UΓ′) = ∅. Wir machen noch folgende Annahmen über die Struktur Γ = T.C und U = (S, C_{1}) und wir zerlegen die Substitution S in zwei Teile durch die Definitionen S_{1} = S \ \{\overline{α}\} , S_{2} = S_{|\{\overline{α}\}}. Damit können wir eine Reihe von Äquivalenzen zeigen.

Uσ  ≤_{UΓ}^{g}  σ′
⇔ ∀\overline{α}.S_{1}C′′ ⇒ S_{1}τ ≤_{UΓ}^{g}  ∀\overline{β}.C′ ⇒ Sτ
⇔ S_{1}τ ≤^{S_{2}} Sτ ∧ UΓ, C′ ⊢ S_{2}S_{1}C′′
⇔ wahr per Definition ∧  UΓ ⊢ SC′′
⇔  wahr wegen  UΓ ↓ impliziert UΓ ⊢ SΓ und SC′′ ⊆ SΓ

Dies ist in folgenden Lemma zusammengefaßt.

Lemma 4.3.6 (einfache Rechtserweiterung)

Sei das Tupel (τ, Γ) gegeben und eine eingeschränkte Substitution U mit Terminierungseigenschaft UΓ ↓ dann gilt die Kommutationabschätzung

U ∘ g(τ, Γ) ≤ g ∘ U(τ, Γ)

oder graphisch dargestellt

[figure: (τ, Γ); g; U; σ; U; Uσ; ≤_{UΓ}^{g}; (Uτ, UΓ); g; σ′]

Nun wollen wir dieses Resultat erweitern, wobei wir berücksichtigen wie sich die Generalisierung verhält beim Verbrauch von Einschränkungen aus der Typothese. Dieser Verbrauch von Einschränkungen ist das Verhalten, daß bei der Quantifizierung Einschränkungen aus der Typothese entnommen werden und in dem Typschema gebunden werden. Wir definieren nun die Abhängigkeitsbeziehung zwischen Typvariablen in einer Typothese Γ als eine Beziehung →⊆ tv(Γ) × tv(Γ). Es gelte α → β gdw o : β → τ ∈ Γ und α ∈ tv(τ). Also α → β sagt uns, daß die Typvariable α nur dann mit der Regel (∀I) ∀-quantifiziert werden kann, wenn die Typvariable β vorher quantifiziert wurde und dabei die Einschränkung o : β → τ verbraucht wurde, so daß die Nebenbedingung α ∈ tv(Γ \ α) nicht mehr verletzt werden kann. Wir nennen eine Typvariable α basiert wenn Sie eingeschränkt ist (also α ∈ rv(Γ)) und frei in einer Deklaration auftritt (also α ∈ tv(T)) wobei die Typothese die Struktur Γ = T.C habe. Die basierte Typvariable α kann also niemals quantifiziert werden. Das führt zu folgenden Begriffsdefinitionen :

Γ ist nicht zyklisch gdw die →-Beziehung keine Zyklen hat.

β nicht bindbar in Γ gdw β ist basiert oder kann durch einen →-Pfad eine basierte Typvariable erreichen.

C′ nicht bindbar in Γ gdw eine Menge V von nicht bindbaren Typvariablen in Γ ist und C′ = Γ_{V} gilt.

(Γ, τ) ist völlig benutzt gdw für jede eingeschränkte Typvariable α ∈ rv(Γ) entweder die Beziehung α → β gilt oder α basiert ist oder α frei in τ auftritt also α ∈ tv(τ).

(Γ, τ) ist rein gdw die Typothese Γ nicht zyklisch ist und (Γ, τ) völlig benutzt.

Wir möchten nun die Beziehung zwischen den gebunden Typvariablen verstehen, wenn die Generalisierung vor oder nach der Anwendung einer eingeschränkten Substitution ausgeführt wird. Durch die neue Charakterisierung der nicht bindbaren Typvariablen erhalten wir das Resultat, daß die Eigenschaft der Nichtbindbarkeit eine Invariante unter Anwendung von eingeschränkten Substitutionen ist. Dies folgt aus einer Betrachtung des Verhaltens von →-Pfaden unter Anwendung von engeschränkten Substitutionen. Technisch wird der Schritt in zwei Lemmas aufgeteilt

Lemma 4.3.7 Sei eine Typothese T.C und eine terminierende Substitutionsanwendung (also ST.C ↓) gegeben. Wenn wir eine Einschränkung r_{β} ∈ C über eine determinierte Typvariable β ∈ dv(S) haben dann folgt, daß eine freie Typvariable in der determinierten Einschränkung α′ ∈ tv(Sr_{β}) auch in determinierten Argumenttyp auftritt α′ ∈ tv(Sβ). Beweis: Wir führen einen Widerspruchsbeweis. Wir nehmen also die Gültigkeit aller Vorbedingungen an aber auch α′ ∉ tv(Sβ). Wenn die Einschränkung die Struktur r_{β} = o : β → τ ∈ C hat, und wir für die determinierte Typvariable β ∈ dv(S) die Bindung Sβ = K\overline{τ} annehmen, dann gibt uns die Terminierung ST.C ↓ eine Instanzdeklaration o : σ_{K} ∈ T. Für die Struktur von σ_{K} nehmen wir σ_{K} = ∀\overline{α}.C′ ⇒ K\overline{α} → τ′ an. Desweiteren folgt aus der Termination, daß die Substitution S ein Unifikator der Typen K\overline{α} → τ′ und β → τ ist. Also haben wir die Gleichung Sτ′ = Sτ und die Struktur von σ_{K} gibt die Variablenbedingung tv(τ′) ⊆ \{\overline{α}\} (1) . Aus der Vorbedingung α′ ∈ tv(Sr_{β}) und der Widerspruchsannahme α′ ∉ tv(Sβ) folgt mit der Struktur der Einschränkung die Eigenschaft α′ ∈ tv(Sτ). Also gibt es einen Pfad p in dem Typ, daß die Gleichungen Sτ|p = α′ = Sτ′|p gelten. Die Nutzung der Variablenbedingung (1) gibt uns eine Teilpfad p′ ◁ p mit τ′|p′ = α_{i} also auch die Elementbeziehung α′ ∈ tv(Sα_{i}). Letztlich führt nun die Unifikationseigenschaft zur Gleichung Sβ = SK\overline{α} aus welcher direkt der Widerspruch α′ ∈ tv(Sβ) zu sehen ist □.

Bemerkung: Wir betrachten nun Einträge der Typothese x : σ ∈ T.C, so daß aus der Bedingung β ∈ tv(σ) mit obigen Bedingungen (also β ∈ dv(S) ∧ r_{β} ∈ C ∧ α′ ∈ tv(Sr_{β})) die Elementbeziehung α′ ∈ tv(Sσ) folgt. Wir betrachten zwei Fälle von Typotheseneinträgen. Wenn x : σ eine Einschränkung o′ : β → τ′′ ist, dann besagt der obige Satz, daß eine Kette α → β → γ in der Typothese T.C zu einer neue Abhängigkeit α′ → γ′ in der Typothese ST.C wird. Dabei wird β durch S determiniert und S muß als Umbenennung für Sα = α′ und Sγ = γ′ wirken. Wir nennen dieses Verhalten den Kollaps der Kette α → β → γ unter Substitution S zu einer Kette α′ → γ′ von umbenannten Variablen. In dem Fall, daß der Eintrag x : σ eine Deklaration u : σ oder o : σ_{K} ist, wäre die Typvariable β basiert in T.C. In diesem Fall sagt uns der obige Satz für eine Abhängigkeit α → β, daß die Typvariable α′ eine basierte Typvariable in ST.C ist wenn S die Umbenennung Sα = α′ ausführt.

4.3. KORREKTHEIT UND VOLLSTÄNDIGKEIT DER TYPINFERENZ 101

Lemma 4.3.8 (Invarianz der Nichtbindbarkeit unter Anwendung von Substitution) Sei ein Tupel (T.C, τ) und eine Substitution S gegeben, so daß die Anwendung der Substitution auf das Tupel terminiert. Wenn die Menge von Einschränkungen C nicht bindbar in der Typothese T.C ist dann erhält sich diese Eigenschaft auch für die folgenden Mengen. Die minimale konservative Erweiterung bei Anwendung der Substitution C′ =^{def} mce(S, T.C) und nicht determinierten Einschränkungen C′′ =^{def} S(C \ dv(S)) sind auch im Tupel (ST.C′.C′′, Sτ) nicht bindbar. Man beachte, daß die Mengen von Einschränkungen C′ und C′′ die neue Einschränkungsmenge darstellen bei einer terminierenden Anwendung einer Substitution S(T.C) ↓ ST.C′.C′′. Beweis: Für beide Mengen ist die Nichtbindbarkeit der Einschränkungen nachzuweisen.

r_{α′} = o : α′ → τ ∈ C′ Dann gibt es per Definition der Menge C′ eine Einschränkung r_{α} = o : α → τ′ ∈ C die determiniert ist α ∈ dv(S), so daß die betrachtete Einschränkung zur Auflösung der determinierten Einschränkung benötigt wird r_{α′} ∈ mce(S, T.r_{α}) mit der Variablenbedingung α′ ∈ tv(Sα). Da die Typvariable α nicht bindbar ist, muß sie entweder basiert sein oder in einer basierten Kette α → … → γ auftreten. Die Bemerkung obigem Lemma impliziert, daß dann auch die Typvariable α′ entweder basiert ist oder in einer kollabierten Basiskette auftritt. Also ist α′ auch nicht bindbar.

r_{α′} = o : α′ → τ ∈ C′′ Per Definition der Menge C′′ erhalten wir eine Einschränkung r_{α} = o : α → τ′ ∈ C, so daß die Substitution auf dem Argument der Einschränkung als Umbenennung wirkt Sr_{α} = r_{α′}.Mit dem selben Argument wie im obigen Fall können wir nun von der Nichtbindbarkeit der Typvariable α auf diese Eigenschaft bei α′ schließen.

Man beachte, daß der Beweis niemals von der Tatsache gebraucht gemacht hat, daß die ganze Menge C′ nicht bindbar ist. Wenn wir also eine Situation haben in der nur eine Teilmenge C_{1} ⊆ C nicht bindbar in der Typothese T.C ist, dann ist die minimale Erweiterung C_{2} mit der Terminierungseigenschaft S(T.C_{1}) ↓ ST.C_{2} auch in dem Tupel (ST.C, Sτ) nicht bindbar. Mit diesen Sätzen können wir das volle Lemma zur Rechtserweiterung beweisen.

Lemma 4.3.9 (Rechtserweiterung) Seien zwei Tupel gegeben die durch eine terminierende Anwendung einer eingeschränkten Substitution verbunden sind (T.C_{1}.C′_{1}, τ′) ≤^{(S,C_{2})} (ST.C.C′, τ). Wenn nun auf die beiden Tupel die Generalisierung angewendet wird, dann können wir die Ergebnisse dieser Generalisierung wieder in Beziehung zu einander setzen. Wenn wir also die Berechnungen gen(T.C_{1}.C′_{1}, τ′) = (C_{1}, σ_{1}) und gen(ST.C.C′, τ) = (C, σ) haben, dann sind die Ergebnistupel durch die folgenden Abschätzungen verbunden :

T.C_{1} ≤^{(S,C′_{2})} ST.C ∧ C′_{2} ⊆ C_{2} ∧ Sσ_{1} ≤_{ST.C}^{g} σ

Wir können das graphisch darstellen als

[figure: (T.C_{1}.C′_{1}, τ′); gen; V =(S,C_{2}); (T.C_{1}, σ_{1}); V′=(S,C′_{2}) ∧ C′_{2}⊆C_{2}; (ST.C, Sσ_{1}); Sσ_{1}≤_{ST.C}^{g}σ; (ST.C.C′, τ); gen; (ST.C, σ)]

Man beachte, daß die auftretenden Mengen von Einschränkungen zweigeteilt sind. Die Mengen C_{1} und C enthalten die nicht bindbaren Einschränkungen und sind also vor und nach der Generalisierung vorhanden. Die Mengen C′_{1} und C′ werden bei der Generalisierung aus der Typothese entnommen und in die entstehenden Typschemata eingebunden. Auch der rechte Pfeil für die Vermittlung der Generalisierungsergebnise ist zweigeteilt. Der obere Teil des Pfeil vermittelt durch eine Substitution zwischen den nicht bindbaren Einschränkungsmengen. Der untere Teil des Pfeils vermittelt zwischen den Einschränkungsmengen die in die Typschemen gebunden wurden. Beweis: Auch der Beweis behält die Zweiteilung obiger Bemerkung bei.

Aus den Eigenschaften der Generalisierung wissen wir, daß die Typschemen die Struktur σ_{1} = ∀\overline{α}.C′_{1} ⇒ τ′ und σ = ∀\overline{β}.C′ ⇒ τ haben müssen. Wir teilen nun die Substitution S auf in den Teil der auf die gebundenen Variablen von σ_{1} wirkt S_{1} =^{def} S_{|\{\overline{α}\}} und die Substitution die auf den Rest wirkt S_{2} = S_{|dom(S)\\{\overline{α}\}}, damit gilt auch die Gleichung S = S_{1} ∘ S_{2}. Nun ist bei der Anwendung der Substitution S auf das Typschema σ_{1} nur die Teilsubstitution auf die ungebunden Typvariablen zu beachten, also Sσ_{1} = ∀\overline{α}.S_{2}C′_{1} ⇒ S_{2}τ′. Für den Beweis der Abschätzung Sσ_{1} ≤_{ST.C}^{g} σ müssen wir einen vermittelnde Substitution S′ finden, so daß die Abschätzung von Substitutionen S_{2}τ′ ≤^{S′} τ (1) und die Normalisierungsbeziehung ST.C.C′ ⊢ S′S_{2}C′_{1} (2) gültig wird. Wenn wir die Teilsubstitution auf die gebunden Typvariablen als vermittelnde Substitution nehmen S′ =^{def} S_{1}, dann ist die Bedingung (1) einfach erfüllt, weil die Gleichungen τ = Sτ′ = S_{1}S_{2}τ′ gelten. Die Voraussetzung des Lemmas war, daß die Anwendung der eingeschränkten Substitution V = (S, C_{2}) auf die Typothese terminiert V T.C_{1}.C′_{1} ↓ ST.C.C′, also terminiert auch die Anwendung der einfachen Substitution S auf die Typothese T.C_{1}.C′_{1}. Die Typothese ST.C.C′ ist dann eine konservative Erweiterung der Typothese ST.C_{1}.C′_{1}. Also gilt die Normalisierungsbeziehung ST.C.C′ ⊢ S_{1}S_{2}C′_{1} = SC′_{1} womit die Bedingung (2) gezeigt ist.

Nun benutzen wir die Invarianz der Nichtbindbarkeit unter Anwendung von eingeschränkter Substitution. Es liegt also eine Beziehung zwischen Mengen nicht bindbaren Einschränkungen C_{1} und C vor. Lemma 4.3.8 besagt, daß die minimale Erweiterung C′′_{2} in der Terminationsbeziehung S(T.C_{1}) ↓ ST.C′′_{2} im Tupel (ST.C.C′, τ) nicht bindbar ist, also gilt die Teilmengenbeziehung C′′_{2} ⊆ C auf den Mengen nicht bindbarer Einschränkungen. Wenn wir die eingeschränkte Substitution (S, C) benutzen erhalten wir offensichtlich die Abschätzung T.C_{1} ≤^{(S,C)} ST.C. Wegen der Teilmengenbeziehung der Typothesen ST.C ⊆ ST.C.C′ können wir annehmen, daß eine Teilmenge C′_{2} ⊆ C_{2} genügt um die vermittelnde eingeschränkte Substitution für die Beziehung T.C_{1} ≤^{(S,C′_{2})} ST.C zu erhalten. Die Einschränkungen aus der Differenz von C_{2} und C′_{2} sind in der Menge C′ der gebunden Einschränkungen zu finden.

Lemma 4.3.10 (Nichtverbrauch von Einschränkungen) Sei eine Herleitung d : T.C.C′ ⊢^{d}e : τ gegeben, so daß bei Anwendung der Generalisierung gen(T.C.C′, τ) = (C, σ) die Einschränkungsmenge C′ verbraucht wird, dann können wir die Herleitung d so transformieren, daß bei anschließender Generalisierung die Einschränkungsmenge des Ergebnisses mit der Einschränkungsmenge der Typothese aus d übereinstimmt. Formal:

d′ : T.C.C′.C′′ ⊢^{d}e : τ′ ∧ gen(T.C.C′.C′′, τ′) = (C.C′, σ)

Beweis: Wegen der Eigenschaften der Funktion gen wissen wir über die Struktur der Typschemas σ = ∀\overline{α}.C′ ⇒ τ und die Verschiedenheit von gebundenen und freien Typvariablen \{\overline{α}\} ∩ tv(T.C) = ∅. Nun nehmen wir eine Sequenz von neuen Typvariablen \overline{β} und definieren eine Umbenennung mit den neuen Namen S = [\overline{β}/\overline{α}]. Wenn wir die Umbenennung S auf die Herleitung d anwenden erhalten wir eine neue Herleitung d′ : T.C.SC′ ⊢^{d}e : Sτ wobei wir die die Gleichung ST.C.C′ = T.C.SC′ benutzt haben, die aus der Typvariablenbedingung folgt. Bei Anwendung der Funktion gen auf das Tupel zur neuen Herleitung gen(T.C.SC′, Sτ) = (C, σ) können wir feststellen, daß das Ergebnis das selbe bleibt weil das Typschema σ invariant unter Umbenennung der gebundenen Typvariablen ist. Wir können nun die gesuchte Menge von Einschränkungen C′′ =^{def} SC′ und den Typ τ′ =^{def} Sτ definieren. Die Generalisierung verbraucht nur die Menge C′′ wenn wir also die Herleitung d′ um die Menge C′ erweitern, dann erhalten wir das Resultat

d′′ : T.C.C′.C′′ ⊢^{d}e : τ′ ∧ gen(T.C.C′.C′′, τ′) = (C.C′, σ)

4.3.5 Eigenschaften der Typisierung

Die Korrektheits- und Vollständigkeitseigenschaften für die Typisierung werden jeweils in zwei Schritten erreicht. Dazu wird das syntaktische System ⊢^{d} definiert, daß zwischen dem logischen System O und dem algorithmischen System W liegt. Das syntaktische System hat die Eigenschaft, daß es für jedes gegebene Typisierungsproblem (Γ, e), höchstens eine Herleitung gibt für die Aussage Γ ⊢^{d}e : τ, im Gegensatz zu System O wo durch die Verwendung der Regeln (∀I) und (∀E) mehrere Herleitungen für die Aussage Γ ⊢ e : τ möglich sind, wenn die Aussage herleitbar ist. Die Beziehung zwischen den logischen Aussagen aus System O und den Resultaten der Berechnung der algorithmischen System W werden also immer über syntaktische Aussagen führen. Diese Methodik zu Beweis der Typisierungseigenschaften ist in [Jon92] ausgeführt worden. Am Beispiel der Korrektheitseigenschaft des Typisierungsalgorithmus ist dieses Vorgehen in zwei Schritten zu sehen. Im Abschnitt 4.3.6 werden die folgenden zwei Lemmas bewiesen : Lemma 4.3.13 (Korrektheit von ⊢^{d}) Wenn Γ ⊢^{d}e : τ dann Γ ⊢ e : τ. Lemma 4.3.14 (Korrektheit von ⊢^{W} relativ zu ⊢^{d}) Wenn UΓ ⊢^{W} e : τ dann UΓ ↓ und UΓ ⊢^{d}e : τ. Daraus folgt direkt das Korollar

Korrolar 4.3.11 (absolute Korrektheit von ⊢^{W}) Wenn UΓ ⊢^{W} e : τ dann UΓ ↓ und UΓ ⊢ e : τ.

Die Vollständigkeitseigenschaft für das algorithmische System wird in der selben Art erreicht. Im Abschnitt 4.3.7 werden die zwei folgenden Lemma bewiesen: Lemma 4.3.15 (Vollständigkeit von ⊢^{d}) Wenn Γ ⊢ e : σ dann existiert C mit rv(C) ∩ tv(Γ, σ) = ∅ so daß gilt:

Γ.C ⊢^{d}e : τ ∧ g(Γ.C, τ) = σ′ ∧ σ′ ≤_{Γ.C}^{g} σ

Lemma 4.3.16(relative Vollständigkeit von ⊢^{W}) Wenn UT.C ⊢^{d}e : τ dann

U′T.C′ ⊢^{W} e : τ′ ∧ U′ ≤^{V} U ∧ (U′T.C′, τ′) ≤^{V} (UT.C, τ)

Als Korollar erhalten wir wieder die absolute Vollständigkeitseigenschaft.

Korrolar 4.3.12 (absolute Vollständigkeit von ⊢^{W}) Wenn UΓ ⊢ e : σ dann ∃C mit rv(C) ∩ tv(Γ, σ) = ∅ und

U′Γ′ ⊢^{W} e : τ′ ∧ U′ ≤^{V} U ∧ U′Γ′ ≤^{V} UΓ.C

so daß V σ′ ≤_{UΓ.C}^{g} σ gilt für σ′ =^{def} g(U′Γ′, τ′). Beweis: Wir wenden Lemma 4.3.15 auf die Herleitung der logischen Aussage UΓ ⊢ e : σ an. Wir erhalten die Einschränkung C mit der benötigten Eigenschaft:

UΓ.C ⊢^{d}e : τ ∧ g(UΓ.C, τ) = σ′′ (1) ∧ σ′′ ≤_{UΓ.C}^{g} σ (2)

Wir wenden Lemma 4.3.16 auf die Herleitung der syntaktischen Aussage UΓ.C ⊢^{d}e : τ an und erhalten

U′T.C′ ⊢^{W} e : τ′ ∧ U′ ≤^{V} U ∧ (U′T.C′, τ′) ≤^{V} (UT.C, τ) (3)

(T AUT)^{d}  \frac{x : σ ∈ Γ  σ ≤_{Γ}^{g} τ}{Γ ⊢^{d}x : τ}

(→ I)^{d}  \frac{Γ, u : τ ⊢^{d}e : τ′}{Γ ⊢^{d}λu.e : τ → τ′}

(→ E)^{d}  \frac{Γ ⊢^{d}e : τ′ → τ  Γ ⊢^{d}e′ : τ′}{Γ ⊢^{d}e e′ : τ}

(LET)^{d}  \frac{Γ′ ⊢^{d}e : τ′ gen(τ′, Γ′) = (σ, Γ) Γ, u : σ ⊢^{d}e′ : τ}{Γ ⊢^{d}let u = e in e′ : τ}

Abbildung 4.4: Das syntaktische System

Die Benutzung von (1) und (3) führt zu g ∘ V (U′T.C′, τ′) = σ′′. Wir können nun das Lemma zur Rechtserweiterung auf der Instanzrelation benutzen um die Beziehung V σ′ ≤_{UΓ.C}^{g} σ′′ zu erhalten, wobei die Definition σ′ =^{def} g(U′T.C′, τ′) benutzt wurde. Mit (2) und Benutzung der Transitivität der Instanzrelation erhalten die gesuchte Beziehung V σ′ ≤_{UΓ.C}^{g} σ □.

4.3.6 Korrektheit des syntaktischen Systems

Lemma 4.3.13 (Korrektheit von ⊢^{d}) Wenn es eine syntaktische Herleitung Γ ⊢^{d}e : τ gibt dann gibt es auch eine logische Herleitung Γ ⊢ e : τ. Beweis: Der Beweis wird per Induktion über die Struktur der syntaktischen Herleitung geführt, dabei wir die gegebene Herleitung in eine logische Herleitung für das System O übersetzt. Wir analysieren die letzte angewendete Regel der syntaktischen Herleitung und wenden dabei die Induktionshypothese auf die Prämissen der Regel an. Also gibt es für jede Regel des syntaktischen Systems einen Fall zu untersuchen.

(T AUT)^{d} die letzte Regelanwendung war

(T AUT)^{d} \frac{x : σ ∈ Γ σ ≤_{Γ}^{g} τ}{Γ ⊢^{d}x : τ}

Die Definition der generischen Instanzbeziehung wird angewendet auf die rechte Prämisse σ ≤_{Γ}^{g} τ und gibt uns für die linke Prämisse x : σ ∈ Γ eine logische Herleitung d : Γ ⊢ x : τ.

(T AUT)^{W}  \frac{x : ∀\overline{α}.C ⇒ τ ∈ Γ  \overline{β} neu}{[\overline{β}/\overline{α}]Γ, C ⊢^{W} x : [\overline{β}/\overline{α}]τ}

(→ I)^{W}  \frac{UΓ, u : α ⊢^{W} e : τ  α neu}{UΓ ⊢^{W} λu.e : Uα → τ}

(→ E)^{W}  \frac{UΓ ⊢^{W} e : τ  U′UΓ ⊢^{W} e′ : τ′ U′τ ∼^{V}_{U′UΓ} τ′ → α α neu}{V U′UΓ ⊢^{W} e e′ : V α}

(LET)^{W}  \frac{UΓ′ ⊢^{W} e : τ′ gen(τ′, UΓ′) = (σ, UΓ) U′UΓ, u : σ ⊢^{W} e′ : τ}{U′UΓ ⊢^{W} let u = e in e′ : τ}

Abbildung 4.5: Typinferenz Algorithmus W

(→ I)^{d}, (→ E)^{d} Die logischen Regeln des System O (→ I), (→ E) sind syntaktisch gleich. Also erhalten wir durch Anwendung der Induktionshypothese auf die Prämissen der syntaktischen Regel eine logische Herleitung der Aussage. Die Anwendung der korrespondierenden logischen Regel fügt die Prämissen dann zu der gesuchten Herleitung zusammen.

(LET)^{d} in diesem Fall war die letzte Regelanwendung

(LET)^{d} \frac{Γ′ ⊢^{d}e : τ′ gen(τ′, Γ′) = (σ, Γ) Γ, u : σ ⊢^{d}e′ : τ}{Γ ⊢^{d}let u = e in e′ : τ}

Nutzung der Induktionshypothese auf der linken Prämisse gibt die logische Herleitung der Aussage Γ′ ⊢ e : τ′. Wenn darauf die Funktion gen angewendet wird erhalten wir die logische Herleitung Γ ⊢ e : σ (1) (sieh auch 2). Anwendung der Induktionshypothese auf die rechte Prämisse ergibt die logische Herleitung für Γ, u : σ ⊢ e : τ (2) .

Nun können wir die Regel (LET) anwenden, wobei wir (1) für die linke Prämisse und (2) für die rechte Prämisse nehmen um damit die logische Herleitung für die Aussage Γ ⊢ let u = e in e′ : τ zu erhalten □.

Lemma 4.3.14 (Korrektheit von ⊢^{W}) Gegeben die Berechnung UΓ ⊢^{W} e : τ dann terminiert die Anwendung der SubstitutionUΓ ↓ Γ′ und es gibt eine syntaktische Herleitung Γ′ ⊢^{d}e : τ. Beweis:

(T AUT)^{W} Die letzte Regelanwendung war

(T AUT)^{W} \frac{x : ∀\overline{α}.C′ ⇒ τ ∈ Γ \overline{β} neu}{[\overline{β}/\overline{α}]Γ, C′ ⊢^{W} x : [\overline{β}/\overline{α}]τ}

Wir definieren die neue Typothese Γ′ = [\overline{β}/\overline{α}]Γ.C′, dann ist offensichtlich der benutzte Eintrag immer noch in der Typothese x : σ ∈ Γ′. Desweiteren gilt die Abschätzung σ ≤_{Γ′}^{g} [\overline{β}/\overline{α}]τ wegen der Normalisierungsbeziehung Γ ⊢ [\overline{β}/\overline{α}]C′. Das sind die benötigten Daten um die Regel (T AUT)^{d} anzuwenden und so eine syntaktische Herleitung für die Aussage Γ′ ⊢^{d}x : [\overline{β}/\overline{α}]τ zu gewinnen.

(→ I)^{W} Hier ist eine Berechnung gegeben mit letzter Regelanwendung:

(→ I)^{W} \frac{UΓ.u : α ⊢^{W} e : τ α neu}{UΓ ⊢^{W} λu.e : Uα → τ}

Wir wenden die Induktionshypothese auf die Prämisse an und erhalten die Terminierungsbeziehung U(Γ.u : α) ↓ Γ′ und die syntaktische Herleitung Γ′ ⊢^{d}e : τ. Der Abschnitt 4.3.3 gibt uns die Elementbeziehung u : Uα ∈ Γ′, also können wir die Regel (→ I)^{d} auf die Herleitung Γ′_{u}, u : Uα ⊢^{d}e : τ anwenden und erhalten die gesuchte Herleitung Γ′ ⊢^{d}λu.e : Uα → τ □

(→ E)^{W}

(→ E)^{W} \frac{UΓ ⊢^{W} e : τ U′UΓ ⊢^{W} e′ : τ′ U′τ ∼^{V}_{U′UΓ} τ′ → α α neu}{V U′UΓ ⊢^{W} e e′ : V α}

linke Prämisse IH gibt die Terminierungsbeziehung UΓ ↓ Γ_{1} und die Her-

leitung Γ_{1} ⊢^{d}e : τ (1) mittlere Prämisse Anwendung der Induktionshypothese gibt die Termi-

nierungsbeziehung U′UΓ ↓ Γ_{2} mit obiger Typothese läßt sich das zu U′Γ_{1} ↓ Γ_{2} (2) umformulieren, zusätzlich haben wir die syntaktische Herleitung Γ_{2} ⊢^{d}e′ : τ′ (3) . Mit den Aussagen (1) und (2) können wir das Korrolar 4.3.5 (Anwendung von eingeschränkter Substitution auf syntaktische Herleitungen) anwenden und erhalten so die syntaktische Herleitung Γ_{2} ⊢^{d}e : U′τ (4) .

rechte Prämisse Die Definition des allgemeinsten eingeschränkten Unifikators gibt uns die Terminierungsbeziehung V U′UΓ ↓ Γ_{3} unter Nutzung der obigen Typothese ist das V Γ_{2} ↓ Γ_{3}. Damit haben wir wieder die Möglichkeit nach Korrolar 4.3.5 die eingeschränkte Substitution V auf die bisher erhaltenen syntaktischen Herleitungen anzuwenden. So erweitern wir (3) zur Herleitung von Γ_{3} ⊢^{d}e′ : V τ′ (5) und erweitern (4) zur Herleitung von Γ_{3} ⊢^{d}e : V U′τ (6) . Die Unifikationseigenschaft gibt uns die Gleichung V U′τ = V τ′ → V α damit können wir die Aussage (6) zu Γ_{3} ⊢^{d}e : V τ′ → V α (7) umschreiben.

Konklusion Unter Nutzung der oben hergeleiteten Daten können wir die Regel (→ E)^{d} anwenden und erhalten so die gesuchte syntaktische Herleitung. Γ_{3} = V U′UΓ.

(→ E)^{d} \frac{(7)Γ_{3} ⊢^{d}e : V τ′ → V α Γ_{3} ⊢^{d}e′ : V τ′ (5)}{Γ_{3} ⊢^{d}e e′ : V α}

(LET)^{W}

(LET)^{W} \frac{UΓ′ ⊢^{W} e : τ′ gen(τ′, UΓ′) = (σ, UΓ) U′UΓ.u : σ ⊢^{W} e′ : τ}{U′UΓ ⊢^{W} let u = e in e′ : τ}

linke Prämisse Wir wenden die Induktionshypothese an, um die Herleitung UΓ′ ⊢^{d}e : τ′ (8) zu erhalten.

rechte Prämisse Wir wenden die Induktionshypothese an, um die Herleitung U′UΓ ⊢^{d}e′ : τ (9) zu erhalten.

mittlere Prämisse Die IH auf der linken Prämisse gibt die Terminierungsbeziehung U′UΓ ↓. Damit können wir das Satz 4.3.3 (Linkserweiterung) benutzen und erhalten so eine Kommutation für die Anwendung der eingeschränkten Substitution U und der Funktion gen. Das ist die Berechnung (U′σ, U′UΓ) = gen(U′τ′, U′UΓ′) (10) . Lemma Korrolar 4.3.5 erlaubt wegen U′UΓ′ ↓ die Anwendung der eingeschränkten Substitution U′ auf die Herleitung (8) , woraus die Herleitung U′UΓ′ ⊢^{d}e : U′τ (11) folgt.

Konklusion Nun sammeln wir die Daten zusammen und wenden die Regel (LET)^{d} an.

(LET)^{d} \frac{\begin{matrix}(11) U′UΓ′ ⊢^{d}e : U′τ′ \\ (10) g(U′τ′, U′UΓ′) = (U′σ, U′UΓ) \\ (9) U′UΓ.u : σ ⊢^{d}e′ : τ \end{matrix}}{U′UΓ ⊢^{d}let u = e in e′ : τ}

4.3.7 Vollständigkeit der Typinferenz

Das Beweisvorgehen ist dual zu dem Korrektheitsbeweis. Mit struktureller Induktion über Herleitungen im logischen System wird gezeigt, daß die Typinferenzberechnung terminiert und eine allgemeinste Lösung des Typisierungsproblems berechnet. Dabei werden an den entscheidenden Stellen die Vollständigkeit der Unifikation und das Rechtserweiterungslemma benutzt. Wir werden erst die Resultate verbal benennen und dann formal die Induktionhypothese vorstellen die bewiesen wird.

Vollständigkeit des syntaktischen Systems bedeutet, wenn es eine Lösung für ein Typisierungsproblem im logischen System gibt, dann gibt es auch eine Lösung im syntaktischen System in der die Typothese aus denselben Deklaration und einer neuen Einschränkungsmenge besteht, so daß die Generalisierung der syntaktischen Lösung allgemeiner als die gegebene logische Lösung ist. Wir formulieren diese Aussage um für die technische Durchführung des Beweises. Zu einer logischen Herleitung läßt sich eine Menge von Einschränkungen finden, so daß wir eine syntaktische Herleitung konstruieren können.

Lemma 4.3.15 (Vollständigkeit von ⊢^{d}) Gegeben eine logische Herleitung Γ ⊢ e : σ, dann gibt es eine Menge von Einschränkungen C welche die logische Lösung nicht einschränken rv(C) ∩ tv(Γ, σ) = ∅, so daß aus die logische Herleitung zu einer syntaktischen Herleitung transformiert werden kann :

\begin{aligned}& Γ ⊢ e : σ ⇝ Γ.C ⊢^{d}e : τ ∧ g(Γ.C, τ) = σ′ ∧ σ′ ≤_{Γ.C}^{g} σ \\ ∧ & Γ ⊢ e : τ ⇝ Γ.C ⊢^{d}e : τ \end{aligned}

Beweis: Wir nehmen o.b.d.A. an, daß die Herleitung Γ ⊢ e : σ normalisiert ist da jede logische Herleitung normalisiert werden kann. In der Herleitung tritt also die Folge (∀I)(∀E) nicht auf. Folgen von Quantoreneliminationen treten nur nach der (T AUT) Regel auf. Folgen von Quantoreneinführungen treten nur vor der linken Prämisse der (LET) Regel auf. Der Beweis wird per Induktion auf der Struktur der logischen Herleitung geführt. Es ist für jede Regel des logischen Systems ein Fall zu untersuchen, wobei wir annehmen, daß die untersuchte Regel die letzte Angewendete in der Herleitung ist.

(T AUT)

(T AUT) Γ ⊢ x : σ (x : σ ∈ Γ)

Wir haben die Voraussetzung x : σ ∈ Γ und nehmen für die Struktur des Typschemas σ = ∀\overline{α}.C ⇒ τ an. Natürlich gilt dann die generische Instanzbeziehung σ ≤_{Γ.C}^{g} τ mit welcher wir die Regel (T AUT)^{d} anwenden können um Γ.C ⊢^{d}x : τ herzuleiten. Die Nebenbedingungen sind einfach zu sehen.

g(Γ.C, τ) = σ′ ∧ σ′ ≤_{Γ.C}^{g} σ

(∀I) Die zuletzt angewandte Regel war

(∀I) \frac{Γ.π_{α} ⊢ e : σ′′ (α ∉ tv(Γ))}{Γ ⊢ e : ∀α.π_{α} ⇒ σ′′}

Wir benutzen die Definition σ =^{def} ∀α.π_{α} ⇒ σ′′. Wir wenden die Induktionshypothese auf die Prämisse an und erhalten folgende Daten.

Γ.π_{α}.C′ ⊢^{d}e : τ ∧ g(Γ.π_{α}.C′, τ) = σ′ ∧ σ′ ≤_{Γ.π_{α}.C′}^{g} σ′′

Wir definieren die neue Einschränkungsmenge C =^{def} C′.π_{α}, dann führt die Konfliktfreiheit aus der IH rv(C′) ∩ tv(Γ.π_{α}, σ′′) = ∅ und die Konfliktfreiheit aus der Regelanwendung α ∉ tv(Γ) zu der Konfliktfreiheit der erweiterten Typothese α ∉ tv(Γ.C′). Aus der syntaktischem Charakterisierung der der generischen Instanzbeziehung können wir schließlich die Abschätzung σ′ ≤_{Γ.C}^{g} ∀α.π_{α} ⇒ σ′′ = σ herleiten.

(∀E)Die zuletzt angewendete Regel war

(∀E) \frac{Γ ⊢ e : ∀α.π_{α} ⇒ σ′′ Γ ⊢ [τ/α]π_{α}}{Γ ⊢ e : [τ/α]σ′′}

Wir definieren σ =^{def} [τ/α]σ′′. Es gibt zwei Fälle für das Typschema σ zu betrachten, damit ergibt sich dann auch der zu zeigende Teil der Induktionshypothese :

σ ist ein Typschema Die Anwendung der Induktionshypothese auf die linke Prämisse ergibt die syntaktische Herleitung Γ.C ⊢^{d}e : τ,so daß bei Generalisierung σ′ =^{def} g(Γ.C, τ) die Abschätzung σ′ ≤_{Γ}^{g} ∀α.π_{α} ⇒ σ′′ gilt. Wir habe nur noch die Abschätzung σ′ ≤_{Γ.C}^{g} [τ/α]σ′′ = σ zu zeigen, was aber einfach eine Eigenschaft der generischen Instanzbeziehung ist.

σ ist ein Typ Wir definieren τ =^{def} σ. Nun müssen wir eine syntaktische Herleitung für die Aussage Γ.C ⊢^{d}e : τl konstruieren. Aus unserer Voraussetzung, daß die logische Herleitung normalisiert ist führt zu der Beobachtung, daß der Term e nicht zusammengesetzt ist. Der Term e ist also eine Termvariable x. Die einzig mögliche normalisierte Herleitung, ist mit der Regel (T AUT) auf die Elementbeziehung x : σ_{1} ∈ Γ zu beginnen und danach (∀E) Regeln anzuwenden. Dieser Fall ist bereits in der Betrachtung zu Regel (T AUT) abgehandelt.

(→ I)

(→ I) \frac{Γ.u : τ′ ⊢ e : τ}{Γ ⊢ λu.e : τ′ → τ}

Anwendung der Induktionshypothese auf die Prämisse gibt die syntaktische Herleitung Γ.C.u : τ′ ⊢^{d}e : τ. Also können wir die Regel (→ I)^{d} anwenden und erhalten die gesuchte syntaktische Herleitung für Γ.C ⊢^{d}λu.e : τ′ → τ.

(→ E)

(→ E) \frac{Γ ⊢ e : τ′ → τ Γ ⊢ e′ : τ′}{Γ ⊢ ee′ : τ}

linke Prämisse Anwendung der Induktionshypothese gibt die syntaktische Herleitung Γ.C_{1} ⊢^{d}e : τ′ → τ.

rechte Prämisse Anwendung der Induktionshypothese gibt die syntaktische Herleitung Γ.C_{2} ⊢^{d}e′ : τ′.

Konklusion Wir definieren die neue Einschränkungsmenge durch Vereinigung der Einschränkungsmengen welche die Induktionshypothese für den linken und rechten Teil der Herleitung ergeben hat C = C_{1} ∪ C_{2}. Nun erweitern wir die syntaktischen Herleitungen zu T.C ⊢^{d}e : τ′ → τ und T.C ⊢^{d}e′ : τ′. Darauf können wir die Regel (→ E)^{d} anwenden und erhalten die gesucht syntaktische Herleitung.

(LET) Die zuletzt angewendete Regel hatte folgende Form

(LET) \frac{Γ ⊢ e′ : σ Γ, u : σ ⊢ e : τ}{Γ ⊢ let u = e′ in e : τ}

linke Prämisse Anwendung der Induktionshypothese ergibt die Daten.

Γ.C_{1} ⊢^{d}e′ : τ′ (1) ∧ g(Γ.C_{1}, τ′) = σ′ ∧ σ′ ≤_{Γ.C_{1}}^{g} σ (2)

rechte Prämisse Anwendung der Induktionshypothese ergibt die syntaktische Herleitung Γ.C_{2}.u : σ ⊢^{d}e : τ. Wir definieren die neue Einschränkungsmenge C = C_{1} ∪ C_{2} und erweitern damit die obige syntaktische Herleitung Γ.C.u : σ ⊢^{d}e : τ. Wir benutzen die Abschätzung (2) auf Typschemen, dann erweitern wir die in der Abschätzung aufgetretene Einschränkungsmenge C_{1} ⊆ C und erhalten durch Anwendung des Kontravarianzlemmas die syntaktische Herleitung Γ.C.u : σ′ ⊢^{d}e : τ (3) .

Konklusion Nun erweitern wir auch in der Herleitung (1) die Einschränkungsmenge und erhalten die syntaktische Herleitung Γ.C ⊢^{d}e : τ′. Durch Nutzung des Nichtverbrauchs-Lemma 4.3.10 erhalten wir die Erweiterungen

Γ.C.C′ ⊢^{d}e : τ′′ (4) ∧ gen(Γ.C.C′, τ′′) = (Γ.C, σ′) (5)

Schließlich fügen wir die Daten mit einer Regelanwendung von (LET)^{d} zusammen.

(LET)^{d} \frac{\begin{matrix}Γ.C.C′ ⊢^{d}e : τ′′ (4) \\ gen(Γ.C.C′, τ′′) = (Γ.C, σ′) (5) \\ Γ.C ⊢^{d}e′ : τ (3) \end{matrix}}{Γ.C ⊢^{d}let u = e in e′ : τ}

Lemma 4.3.16 (Vollständigkeit von ⊢^{W})

UT.C ⊢^{d}e : τ ⇝ U′T.C′ ⊢^{W} e : τ′ ∧ U′ ≤^{V} U ∧ (U′T.C′, τ′) ≤^{V} (UT.C, τ)

Beweis:

(T AUT)^{d}

(T AUT)^{d} \frac{x : σ ∈ U′′T.C σ ≤_{U′′T.C}^{g} τ}{U′′T.C ⊢^{d}x : τ}

Wir nehmen für die Struktur des Typschemas σ = ∀\overline{α}.C′′ ⇒ τ′′ an. Für die linke Prämisse erhalten wir durch die Charakterisierung der generischen Instanzbeziehung eine Substitution S welche, die Gleichung Sτ′′ = τ (1) und die Normalisierungsbeziehung U′′T.C ⊢ SC′′ (2) erfüllt. Für eine Sequenz neuer Typvariablen \overline{β} führen wir die Definitionen des Ergebnistyps τ′ =^{def} [\overline{β}/\overline{α}]τ′′ der Einschränkungsmenge des ErgebnissesC′ =^{def} C.[\overline{β}/\overline{α}]C′′ und der eingeschränkten Substitution des Ergebnisses U′ =^{def} U′′ ein. Die Anwendung der Regel (T AUT)^{W} auf diese Daten gibt uns die gesuchte Berechnung U′T.C′ ⊢^{W} e : τ′. Durch Nutzung der Aussagen (1) und (2) erhalten wir für die Definitionen V =^{def} S ∘ [\overline{β}/\overline{α}] und U =^{def} V ∘ U′ die gesuchten Abschätzungen U′ ≤^{V} U und (U′T.C′, τ′) ≤^{V} (UT.C, τ).

(→ I)^{d}

(→ I)^{d} \frac{U′′Γ, u : τ_{1} ⊢^{d}e : τ_{2}}{U′′Γ ⊢^{d}λu.e : τ_{1} → τ_{2}}

Für eine neue Typvariable α setzen wir U =^{def} [τ_{1}/α]U′′ und können damit die Prämisse umformulieren UΓ, u : α ⊢^{d}e : τ_{2}. Wenn wir auf diese syntaktische Herleitung die Induktionshypothese anwenden erhalten wir die Berechnung U′Γ′, u : α ⊢^{W} e : τ′_{2} mit den Abschätzungen U′ ≤_{Γ}^{V} U und (U′Γ′.u : α, τ′_{2}) ≤^{V} (UΓ.u : α, τ_{2}). Nun führt die Anwendung der Regel (→ I)^{W} zu der Berechnung U′Γ′ ⊢^{W} e : U′α → τ′_{2} wobei offensichtlich die Abschätzung (U′Γ′, U′α → τ′_{2}) ≤^{V} (UΓ, τ_{1} → τ_{2}) gültig ist.

(→ E)^{d}

(→ E)^{d} \frac{UΓ ⊢^{d}e : τ′ → τ UΓ ⊢^{d}e′ : τ′}{UΓ ⊢^{d}e e′ : τ}

linke Prämisse Anwendung der Induktionshypothese gibt die Daten U_{1}T.C_{1} ⊢^{W} e : τ_{1} und U_{1} ≤^{V_{1}} U und (U_{1}T.C_{1}, τ_{1}) ≤^{V_{1}} (UΓ, τ′ → τ)

(3) . rechte Prämisse In der Untersuchung der linken Prämisse haben wir eine

Faktorisierung der eingeschränkten Substitution U gefunden U = V_{1}U_{1}. Wir nutzen die Faktorisierung zur Reformulierung der rechten Prämisse V_{1}U_{1}T.C_{1} ⊢^{d}e′ : τ′. Wenn zur Anwendung der Induktionshypothese auf die syntaktische Herleitung die Entsprechungen U ≐ V_{1} ∧ T ≐ U_{1}T ∧ C ≐ C_{1} benutzen erhalten wir die Daten U_{2}U_{1}T.C_{2} ⊢^{W} e′ : τ_{2} und U_{2} ≤^{V_{2}} V_{1} und (U_{2}U_{1}T.C_{2}, τ_{2}) ≤^{V_{2}} (V_{1}U_{1}T.C_{1}, τ′) = (UΓ, τ′). Nun benutzen wir die Erweiterbarkeit von algorithmischen Herleitungen durch Einschränkungen. Wir definieren C′ =^{def} C_{1}.C_{2} und Γ′ =^{def} T.C′ und erhalten so die erweiterte Berechnung aus der linken Prämisse U_{1}Γ′ ⊢^{W} e : τ_{1} (4) und die erweiterte Berechnung der rechten Prämisse U_{2}U_{1}Γ′ ⊢^{W} e′ : τ_{2} (5) natürlich gilt auch die erweiterte Abschätzung U_{2}U_{1}Γ′ ≤^{V_{2}} UΓ.

Konklusion Sei α eine neue Typvariable und definieren wir U′′ =^{def} [τ/α]V_{2} dann gelten die Gleichungen

U′′τ_{2} → α = τ′ → τ = V_{1}τ_{1} = U′′U_{2}τ_{1}

Also ist die eingeschränkte Substitution U′′ ein Unifikator der Typen τ_{2} → α und U_{2}τ_{1}. Daraus folgt die Existenz eines allgemeinsten eingeschränkten Unifikators τ_{2} → α ∼^{U_{3}}_{U_{2}U_{1}Γ′} U_{2}τ_{1} (6) . Die Allgemeinheitseigenschaft der eingeschränkten Substitution U_{3} impliziert die Abschätzungen U_{3} ≤^{V_{3}} V_{2} und (U_{3}U_{2}U_{1}Γ′, U_{3}α) ≤^{V_{3}} (V_{2}U_{2}U_{1}Γ′, τ) = (UΓ, τ). All dieses Daten ermöglichen die Anwendung der Regel (→ E)^{W}

(→ E)^{W} \frac{\begin{matrix}U_{1}Γ′ ⊢^{W} e : τ_{1} (4) & U_{2}U_{1}Γ′ ⊢^{W} e′ : τ_{2} (5) \\ τ_{2} → α ∼^{U_{3}}_{U_{2}U_{1}Γ′} U_{2}τ_{1} (6) & α neu \end{matrix}}{U_{3}U_{2}U_{1}Γ′ ⊢^{W} e e′ : U_{3}α}

(LET)^{d}Die letzte angewandte Regel sei

(LET)^{d} \frac{UΓ′′ ⊢^{d}e′ : τ′′ gen(UΓ′′, τ′′) = (UΓ, σ) UΓ, u : σ ⊢^{d}e : τ}{UΓ ⊢^{d}let u = e′ in e : τ}

linke Prämisse Anwendung der Induktionshypothese gibt uns die folgenden Daten

U_{1}T.C_{1} ⊢^{W} e′ : τ_{1} (7) ∧ U_{1} ≤^{V_{1}} U ∧ (U_{1}T.C_{1}, τ_{1}) ≤^{V_{1}} (UΓ′′, τ′′)

mittlere Prämisse Wir können die Generalisierung auf die obigen Daten anwenden und erhalten dann die Berechnung gen(U_{1}T.C_{1}, τ_{1}) = (U_{1}T.C′_{1}, σ_{1}). Mit den Daten der mittleren Prämisse können wir die Linkserweiterung anwenden also Lemma 4.3.9 um für die vermittelnde Substitution V_{1} = (S, C_{2}) die folgenden Abschätzungen herzuleiten

UT.C′_{1} ≤^{(S,C′_{2})} UΓ (8) ∧ C′_{2} ⊆ C_{2} ∧ Sσ_{1} ≤_{UΓ}^{g} σ (9)

Wie in dem Lemma zur Linkserweiterung definieren wir ein neue vermittelnde Substitution V′_{1} =^{def} (S, C′_{2}).

rechte Prämisse Wir benutzen die Abschätzung (8) als Faktorisierung und formulieren die rechte Prämisse damit neu als V′_{1}U_{1}T.C′_{1}.u : σ ⊢^{d}e : τ. Nun wenden wir das Kontravarianzlemma an das besagt, daß wir die Abschätzung (9) benutzen können um das Typschema σ in obiger Herleitung zu ersetzen so erhalten wir V′_{1}U_{1}T.C′_{1}.u : σ_{1} ⊢^{d}e : τ. Auf diese syntaktische Herleitung wenden wir nun die Induktionshypothese an wobei wir die Entsprechungen U ≐ V′_{1} ∧ T ≐ U_{1}T.u : σ_{1} ∧ C ≐ C′_{1} benutzen. So erhalten wir die Daten :

\begin{aligned}& U_{2}U_{1}T.C′′_{2}.u : σ_{1} ⊢^{W} e : τ′ (10) ∧ U_{2} ≤^{V_{2}} V′_{1} \\ ∧ & (U_{2}U_{1}T.C′′_{2}.u : σ_{1}, τ′) ≤^{V_{2}} (V′_{1}U_{1}T.C′_{1}.u : σ_{1}, τ) = (UΓ.u : Sσ_{1}.τ) (11) \end{aligned}

Konklusion Wir setzen eine Menge von Einschränkungen aus den beiden Zweigen zusammen C′ =^{def} C′_{1} ∪C′′_{2}. Mit dieser neuen Einschränkungsmenge erweitern wir die Herleitung (10) zu U_{2}U_{1}T.C′.u : σ_{1} ⊢^{W} e : τ′ (12) . Die eingeschränkten Typvariablen rv(C′′_{2}) können nicht mit den gebundenen Typvariablen des Typschemas σ_{1} in Konflikt geraten. Die Anwendung der Generalisierung bedeutet, daß σ_{1} maximal gebunden ist, so daß die Einschränkungsmenge C′′_{2} in dem Tupel (U_{1}T.C′_{1}, σ_{1}) nicht bindbar ist. Damit ergibt sich die Generalisierungsberechnung :

gen(U_{1}T.(C_{1} ∪ C′′_{2}), τ_{1}) = (U_{1}T.(C′_{1} ∪ C′′_{2}), σ_{1}) = (U_{1}T.C′, σ_{1}) (13)

Wir wenden nun die Erweiterung der Einschränkungsmenge auf die Berechnung (7) an und erhalten U_{1}T.(C_{1} ∪ C_{2}) ⊢^{W} e′ : τ_{1} (14) . Nun müssen noch die Abschätzungen bei Benutzung der zusammengesetzten Menge von Einschränkungen C′ = C′_{1} ∪ C′′_{2} gezeigt werden. Wegen der terminierenden Substitutionsanwendungen V′_{1}U_{1}T.C′_{1} = UΓ = V_{2}U_{2}U_{1}T.C′′_{2} wissen wir, daß die Teile der zusammengesetzten Einschränkungsmenge bei Substitutionanwendung normalisiert werden können. Also die Menge C′_{1} ist bei Anwendung von V′_{1} normalisierbar und die Menge C′′_{2} ist bei Anwendung von V_{2} normalisierbar, wenn wir dies zusammensetzen erhalten wir eine neue eingeschränkte Substitution V mit der Terminierungsbeziehung V U_{2}U_{1}T.C′ = UΓ. Wenn wir U′ = U_{2}U_{1} definieren erhalten wir unter Nutzung der Abschätzung (11) die gesuchten Abschätzungen

U′ ≤^{V} U ∧ (U′T.C′, τ′) ≤^{V} (UΓ, τ)

Schließlich können wir die Regel (LET)^{W} anwenden und erhalten die gesuchte Berechnung im Algorithmus W.

(LET)^{W} \frac{\begin{matrix}(14) & U_{1}T.(C_{1} ∪ C′′_{2}) ⊢^{W} e′ : τ_{1} \\ (13) & gen(U_{1}T.(C_{1} ∪ C′′_{2}), τ_{1}) = (U_{1}T.C′, σ_{1}) \\ (14) & U_{2}U_{1}T.C′, u : σ_{1} ⊢^{W} e : τ′ \end{matrix}}{U′T.C′ ⊢^{W} let u = e′ in e : τ′}

116 KAPITEL 4. ALGORITHMISCHES SYSTEM

Erweiterung des Überladungssystems

Die erste Formulierung des System O war an der natürlichen Darstellung der Typinferenz orientiert. Dadurch waren waren einige Einschränkungen der Typstruktur nötig, welche den Terminierungsbeweis für die Typinferenz ermöglichten. Eine genaue Betrachtung des Terminierungsproblems ergibt eine Lockerung dieser Einschränkungen. Diese neue Formulierung der Beschränkungen kann semantisch begründet werden. Eine Verletzung der Beschränkung bedeutet also einen Programmfehler.

Kern der Erweiterung ist der Begriff der Parametrizität (sh. Abschnitt 2.2), eine Eigenschaft die in Modellen von getypten Sprachen gefunden wurde. Die Parametrizität führt zu einer Methode um aus dem Typ eines Programms Eigenschaften des Programms zu gewinnen. Diese Methodik wurde von parametrischer Polymorphie auf algebraische Datentypen und auf Überladung erweitert. Diese Form der Parametrizität läßt aus dem Typ eines Programms Schlüsse auf folgende Programmeigenschaften zu :

• Divergenz des Programms

• Fehlen von Aufrufen bestimmter überladener Funktionen

• Wohldefiniertheit von überladenen Funktionen.

Die daraus gewonnenen Einsichten werden auf das Problem der Instanzauswahl für die Überladung angewendet. Das Problem besteht darin, zur Übersetzungszeit dem Aufruf einer überladenen Funktion die passende benutzerdefinierte Instanz zuzuordnen. Diese Untersuchung führt also zu einem erweiterten logischen System (genannt System O_{2} ) mit einer operationalen Semantik und einem erweiterten Typinferenzalgorithmus.

Kritische Beispiele

Die folgenden Beispiele treten bei der Nutzung von Überladung auf. Aus den Beispielen resultieren einige Vermutungen, welche in diesem Abschnitt allgemein formalisiert und bewiesen werden. Der Kern dieser Ideen ist der Begriff der Parametrizität welcher durch Untersuchung von Typen Rückschlüsse auf die zugehörigen Programme zuläßt. Eine der Haupteigenschaften des Typisierungsmechanismus für die Überladung ist die Eigenschaft, daß wohlgetypte Programme determiniert sind. Das heißt während der Typinferenz wird ein Programm, in dem die Bedeutung überladener Namen o nicht festgelegt, ist durch die Auswahl von Instanzen o_{τ} festgelegt. Ist diese Auswahl wirklich immer möglich ?? Man betrachte folgendes Programmfragment :

eine Instanz von o o_{L} : ∀α.List α → α ≡ σ_{L}
Programmfragment ...o'(o Nil)...

Die Typinferenz wird folgende Typisierung Nil : List α finden und damit für o die Instanz o_{L} auswählen die Listenargumente verarbeiten kann. Also wird die erste Funktionsanwendung zur Typisierung o_{L}Nil : α führen. Das läßt wiederum die Frage der Instanzauswahl für o' in dem Ausdruck o′(o_{L}Nil : α) offen da der Argumenttyp α nicht zur Auswahl der Instanz von o' beiträgt. Diese Beobachtung könnte zur Annahme führen, daß volle Instanzauswahl unmöglich ist. Das Verfahren soll aber nur die Instanzauswahl für diejenigen überladenen Funktionen ausführen, welche tatsächlich zur Programmausführungszeit aufgerufen werden können. Nun wissen wir aber durch die Parametrizitätseigenschaft, daß die Anwendung des Wertes Nil auf die Funktion o_{L} : σ_{L} in einer strikt auswertenden Sprache nicht terminieren kann. Nachdem nun das Argument divergiert, kann die undeterminierte Funktion o' garnicht aufgerufen werden. Als Hilfe für ein Verständnis dieser Eigenschaft wollen wir das Beispiel einer möglichen Instanzdeklaration für o_{L} untersuchen :

                        inst o x =  case x of

⋮

                                   Nil => e

Um die gesuchte Typisierung List α → α für den Instanzterm zu erhalten muß die Typisierung des Nil Zweiges e : α ergeben. Die einzige Möglichkeit diese geforderte Typisierung zu erhalten ist ein rekursiver Aufruf. In diesem rekursiven Aufruf kann die Typvariable α nicht instantiiert werden also muß der Aufruf die Form o Nil haben, was aber zu einer nicht endenden Rekursion führt.

Eine Optimierung

Wir können eine ähnliche Argumentation für eine Optimierung des Typisierungsvorgangs benutzen. In dem obigen Beispiel hatten wir aus der Typisierung die Divergenz des Ausdrucks o Nil geschlossen und diese Divergenz führte dazu, daß für die überladene Funktion o' in dem Ausdruck o'(o Nil) keine Instanzauswahl nötig war. Wir wollen nun den Fall einer überladenen Funktion o' betrachten welche bei Auswertung der Funktion o aufgerufen werden kann. Diese Situation ist genau bei einer Instanz o_{L} : σ_{L} gegeben bei einem Typ der Form σ_{L} = ∀α.{o′ : α → Int} ⇒ List α → Int. Diese Instanz könnte wie folgt implementiert sein

                     inst o x = case x of

                            Cons(y, ys)  => o' y
                            Nil          => 1

In obigem Beispiel wird die Funktion o' bei Ausführung von o Nil nicht aufgerufen, also ist in solch einem Fall keine Instanzauswahl für o' nötig. Mit Hilfe der Parametrizität kann ohne Kenntnis der Implementierung von o_{L} : σ_{L} nur durch Untersuchung des Typs σ_{L} gezeigt werden, daß bei Auswertung von o Nil entweder o' nicht aufgerufen wird oder bei eventuellem Aufruf o' e die Berechnung des Arguments e divergiert. Also muß für den Aufruf o Nil keine Instanzauswahl zu der Überladungseinschränkung o′ : α → Int vorgenommen werden; diese Überladungseinschränkung wird in der gegebenen Situation leer genannt. Die Einschränkung muß also in dem weiteren Typisierungsvorgang nicht betrachtet werden.

5.1 Das Terminationsproblem für Typkonstruktoren

Die kritischen Beispiele sind alle um den algebraischen Datentyp List und den algebraischen Datenwert Nil konstruiert. Wir wollen nun hier untersuchen, welche Eigenschaften von algebraischen Datentypen diese Konstruktion ermöglichen. Dadurch gelangen wir zu einer Verallgemeinerung welche mit einem Parametrizitätsargument semantisch fundiert werden kann. Wir beginnen hier mit der syntaktischen Definition des Terminationsproblems für Typkonstruktoren. Grundlage der Diskusion ist der Abschnitt 2.3, in dem die algebraischen Datentypen als erweiterte Signatur A = (T , a, D, arg, t) definiert wurden.

Wir wollen nun einen genaueren Blick auf die Eigenschaften der Argumente eines Typkonstruktors werfen. Es folgen einige Beispiele, welche die Definitionen illustrieren werden.

 relevant in a      Tree a   = Leaf a | Brnch (Tree a, Tree a)
 verzichtbar in a    List a   = Nil | Cons (a, List a)
 Cycle ist zyklisch Cycle a  = C Cycle a

Die Relevanz eines Typargumentes bedeutet, daß jeder Datenwert dieses Typs einen Wert dieses Typarguments enthalten muß. Zum Beispiel muß ein Wert des Typs Tree Int eine Integerwert enthalten. Diese Aussage ist nur wahr wenn wir über Werte mit endlichen Pfaden sprechen d.h. wenn ein Wert vom Typ Tree Int den Datenkonstruktor Leaf benutzen muß. Ein unendlicher Baum welcher z.B. durch

let InfTree = Brnch (InfTree, InfTree) in ... definiert sein kann enthält

keinen Leaf Konstruktor. InfTree ist ein Wert vom Typ Tree Int enthält aber keinen Integerwert. Wenn wir uns also auf endliche Werte beschränken erhält der Begriff des relevanten Typarguments einen Sinn. Den Übergang zu endlichen Werten erhalten wir wenn wir eine strikte Auswertungsstrategie für Programme annehmen.

Die Verzichtbarkeit eines Typargumentes erscheint auf den ersten Blick als der duale zu dem obigen Begriff. Man könnte annehmen, daß ein Typargument verzichtbar ist wenn es nicht relevant ist. Das trifft aber nicht ganz genau zu denn falls das erste und das zweite Typargument eines Typkonstruktors verzichtbar ist so folgt daraus noch nicht, daß beide Argumente gemeinsam verzichtbar sind. In unserem Beispiel bedeutet die Verzichtbarkeit des Typkonstruktor List in seinem ersten Argument, daß ein Wert des Typs List Int keinen Integerwert enthalten muß z.B. der Datenkonstruktor Nil ist ein solcher Wert. Wir betrachten nun das folgende Beispiel.

                         T a b = DA a | DB b

In diesem Beispiel sind die beiden Typargumente a und b des Typkonstruktors T verzichtbar; einfach zu sehen bei Benutzung der Datenkonstruktoren DB bzw. DA. Die Verzichtbarkeit der Typargumente für T gilt aber entweder für das erste Argument oder für das zweite Argument aber nicht für beide Argumente. Wenn wir einen weiteren Datenkonstruktor D ohne Argumente in die Definition des Typs T a b aufnehmen würden, so erhielten wir auch noch die Verzichtbarkeit von beiden Typargumenten. Offensichtlich gibt es zu jeder Definition eines algebraischen Datentyps unendliche Datenwerte. Wir nennen einen algebraische Datentyp zyklisch, wenn diese unendlichen Werte die einzigen Werte sind welche die Definition erfüllen.

Es folgen nun zwei formale Charakterisierungen der Terminationseigenschaften von Typkonstruktoren. Beide Charakterisierungen erweitern die Begriffsbildung von Typkonstruktoren auf Typen und Pfaden in Typen. Im folgenden sei V ⊆ V eine Menge von Typvariablen und \overline{α} = α_{1} … α_{n} eine Sequenz von verschiedenen Typvariablen. Es folgt nun eine logische Charakterisierung welche auf der mengentheoretischen Wertsemantik der algebraischen Datentypen basiert.

\begin{aligned}τ ↓ & ⇔ & ∃s ∈ fschm(τ) \\ τ ↑ V & ⇔ & ∃s ∈ fschm(τ) ∀α ∈ V ¬α occ v \\ τ ↓ α & ⇔ & τ ↓ ∧ ∀v ∈ fschm(τ) α occ v \\ T ↓ & ⇔ & T \overline{α} ↓ \\ T ↑ V & ⇔ & T \overline{α} ↑ V \\ T.i ↓ & ⇔ & T \overline{α} ↓ α_{i} \end{aligned}

Die zweite Charakterisierung ist ein System von rekursiven Mengengleichungen welche zu jeder erweiterten Signatur A = (T , a, D, arg, t) eines algebraischen Datentyps aufgestellt werden kann.

relevant  notwendige Benutzung
T ↓ i  gdw ∀D ∈ D_{T} arg(D) ↓ α_{i}
T \overline{τ} ↓ i.p  gdw T ↓ i und \overline{τ}.i ↓ p
τ ↓ α  gdw α ∈ tv(τ) und ∀p ∈ occ(τ, α). τ ↓ p
verzichtbar möglicher Verzicht
T ↑ V  gdw ∃D ∈ D_{T} arg(D) ↑ V
T \overline{τ} ↑ V  gdw ∃V′ ⊆ V_{a(T)} mit T ↑ V′
und V ⊆ ⋂\{V_{i} | α_{i} ∈ V_{a(T)} \ V′ und \overline{τ}.i ↑ V_{i}\}
τ ↑ V  wenn tv(τ) ∩ V = ∅
zyklisch  keine Werte in einer strikt auswertenden Sprache
T ⟲  gdw ∀D ∈ D_{T} für \overline{τ} = arg(D) ∃p ∈ pth(\overline{τ}) mit
\overline{τ} ↓ p und \overline{τ}.p = T′ und T′ = T oder T′ ⟲

Bisher wurden Terme als präfixabgeschlossene Abbildungen von Pfaden p ∈ ℕ^{∗} auf Signaturen dargestellt. Daraus ergab sich der Begriff des Auftretens einer Markierung c an einem Pfad t.p = c oder allgemeiner des Auftretens einer Markierung in einem Term c occ t gwd ∃p. t.p = c. Im folgenden wird der Begriff des relevanten Auftretens einer Markierung c ∈ Var ∪ T in einem Typ τ benötigt welcher durch c rocc τ gdw ∃p.τ ↓ p ∧ τ.p = c definiert sei.

Wir möchten nun die Struktur der Lösung zu obigem Problem definieren. Ein Filter F auf eine Menge V ist ein Menge von Teilmengen von V welche unter der Teilmengenbildung abgeschlossen ist d.h. V ∈ F ∧ V′ ⊆ V ⟹ V′ ∈ F. Wir notieren die Menge der Filter über eine Menge V als F (V). Die Mengen der verzichtbaren Argumenten zu einem Typkonstruktor bilden offensichtlich einen Filter.

Eine Striktheitsmarkierung der Typkonstruktoren ist ein ein Tupel M = (C, r, d) wobei C ⊂ T die Menge der zyklischen Typkonstruktoren ist und die Abbildung r : T → P(V) den Typkonstruktoren die Menge der relevanten Typargumente zuweist und die Abbildung d : T → F (V) den Typkonstruktoren den Filter der verzichtbaren Typvariablen zuweist. Eine Lösung des Terminationsproblems der Typkonstruktoren ist eine Striktheitsmarkierung welche die obigen Gleichungen erfüllt. Für eine Lösungsmarkierung M = (C, r, d) gelten dann also die Implikationen T ∈ C ⇒ T ⟲ und α ∈ r(T) ⇒ T ↓ α und V ∈ d(T) ⇒ T ↑ V.

5.1.1 Terminierungsresultate

Im folgenden wollen wir die Möglichkeit untersuchen aus der Lösung des Terminationsproblems für Typkonstruktoren Schlüsse über die Termination von strikt auswertenden funktionalen Programmen mit algebraischen Datentypen zu ziehen. Wir untersuchen also die geschlossenen Datenwerte v ∈ cval(τ) zu einem reinem Datentyp τ. Für geschlossene Datenwerte ist Lemma 2.3.1, der Satz der eindeutigen Zerlegung von Bedeutung. Der Satz sagt aus, daß es zu jedem Wert v ∈ cval(τ) eindeutig ein endliches Schema s ∈ fschm(τ) gibt, so daß sich der Wert zu v = s\overline{v} zerlegen läßt. Die Definition der der Relevanz für Typkonstruktoren ist durch die Äquivalenz τ ↓ α ⇔ ∀v ∈ cval(τ).α occ v gegeben. Damit ist die Folgerung τ ↓ α ⟹ fschm(∀α.τ) = ∅ offensichtlich. Auf dieser Folgerung basiert nun die Divergenzaussage :

⊢ e : ∀τ ∧ ∃α.α rocc τ ⟹ e ↑ (a)

Da die terminierende Berechnung e ⟶^{∗} v zu einem geschlossenen Datenwert v führen würde und die Subjektreduktion gilt hätten wir einen Wert v ∈ cval(τ) und eine Zerlegung s\overline{v} = v mit s ∈ fschm(τ). Wegen der Relevanz von α gibt es also einen Pfad p mit s.p = α. Wir betrachten nun den Wert v′ = v.p. In der Aussage ⊢ e : ∀τ ist der Typ allquantifiziert also gelten auch die Aussagen ⊢ e : ∀[Int/α]τ und ⊢ e : ∀[Bool/α]τ. Daraus folgen für v′ die zwei widersprüchlichen Typisierungen v′ : Int und v′ : Bool. Damit ist gezeigt, daß es keinen Resultatswert v gibt und also die Auswertung von e divergiert. Nun wollen wir diese Beobachtung noch auf Funktionen f : ∀τ → τ′ insbesondere zwischen zwei reinen Datentypen erweitern. Sei eine Typvariable α ∈ tv(τ → τ′) gegeben, so daß diese Variable im Argumenttyp verzichtbar ist und im Resultatstyp relevant auftaucht (also τ ↑ {α} ∧ α rocc τ′). Dann folgt aus der Verzichtbarkeit der Typvariable die Existenz von Werten v ∈ cval(τ) mit ⊢ v : ∀Sτ und α ∉ dom(S). Wenn f auf diese Werte angewendet wird gilt ⊢ fv : ∀Sτ′ und wegen α rocc Sτ′ folgt die Divergenz fv ↑. Wir können dies in der Aussage

∀v ∈ cval(τ).s\overline{v} = v ∧ s ∈ fschm(∀α.τ) ⟹ fv ↑ (b)

zusammenfassen. Damit können wir aus dem Typ einer Funktion die Divergenz für bestimmte Argumentwerte ablesen.

5.1.2 Leere Constraints

Die obigen Divergenzaussagen (a) und (b) wurden auf Grund der endlichen Repräsentation von algebraischen Datenwerten gewonnen. Diese Endlichkeit folgt aus der strikten Auswertungsstrategie die wir für Programme annehmen. Nun wollen wir einen Schritt weitergehen und aus der Kenntnis der Auswertung eines Programms auf dessen Divergenz schließen. Zuerst müssen wir die Auswertungsstrategie formal definieren Zu jeder Termsprache existiert die Sprache der Kontexte. Die Sprache der Kontexte ensteht indem wir einen Platzhalter [ ] an den Stellen erlauben wo sonst ein Term erwartet wird. Für die Terme von System O erhalten wir so die folgende Kontextsprache.

e ::= x | λx.e | ee′ | let u = e in e′ | inst o = e in e′
E ::= [ ] | λx.E | Ee | eE | let u = E in e | let u = e in E | inst o = E in e | inst o = e in E

Wir können in einem Kontext E den Platzhalter [ ] durch einen Term e ersetzen und erhalten dann wieder einen neuen Term E[e]. Wenn wir den Platzhalter dagegen mit einem Kontext E′ ersetzen, dann erhalten wir einen neuen Kontext E[E′].

Nun erweitern wir den Begriff des Sprachkontextes auf den Begriff eines Beweiskontextes in einer Typisierungsherleitung. Angenommen wir hätten einen Beweisbaum P : Γ ⊢ e : σ wobei die Aussage Γ ⊢ e : σ die Markierung des Wurzelknotens ist und die Prämissen die Markierungen der über die Äste erreichbaren Knoten sind. In diesem Fall bezeichnet P[P′, E : Γ′ ⊢ e′ : σ′] einen Teilbaum P′ des Beweisbaumes P wobei für die Terme die Beziehung E[e′] ≡ e gilt.

Die strikte Auswertungsstrategie für den Lambdakalkül ist gegeben durch eine Teilung der Termgrammatik in Terme e und Werte v.

\begin{aligned}v & ::= & x | λx.e \\ e & ::= & v | ee′ \end{aligned}

und durch die Beschränkung, daß eine Funktion nur auf Wertargumente angewandt werden kann

(λx.e)v ⟶^{β_{v}} [v/x]e

Durch Kontexte wird festgelegt, daß in einem Term höchstens ein Redex vorhanden ist und daß Werte nicht reduziert werden.

E_{v} ::= [] | E_{v}e | vE_{v} ; \frac{e ⟼_{v} e′}{E_{v}[e] ⟼_{v} E_{v}[e′]}

Sei ⊥ der immer divergierende Term und e ↑ die Bezeichnung für Divergenz also ¬∃v.e ↦_{v}^{∗} v bedeutet. Damit läßt sich nun formal zeigen, daß für eine getypten Term e ≡ E[e′] die Resultate von E[⊥] und e gleich sind falls mit Parametrizitätsargumenten die Divergenz von e′ gezeigt werden kann. Das heißt falls bei der Typisierung divergente Terme erkannt werden, können diese Terme aus dem Programm entfernt werden ohne Änderung des Programmresultats.

Satz 5.1.1 Sei e ein geschlossener Term für den die Typisierungherleitung P : ⊢ e∀\overline{α}.τ existiert. Falls die Herleitung eine Teilherleitung P[P′, E : Γ ⊢ e′ : τ′] enthält wobei die Typvariable α ∈ \overline{α} relevant in τ′ auftritt also α rocc τ′ dann wird bei Reduktion von e entweder e′ niemals reduziert oder e divergiert. Beweis:

Es gibt also nur eine Beweisverpflichtung falls e′ reduziert wird im Verlauf der Reduktionvon e. Wir wollen e′ durch die Klammerung < e′ > markieren und nehmen eine Reduktion

e ≡ E[< e′ >] ↦_{v}^{∗} E_{v}[< e′′ >] ≡ e_{3}

an wobei e′′ aus e′ durch Substitution entsteht. Zu zeigen ist e_{3} ↑.

Wir transformieren die Herleitung P durch die Substitutionen [Int/α]P = P_{i} und [Bool/α]P = P_{b} zu zwei neuen Herleitungen. Wir erhalten also zwei Teilherleitungen.

P_{i}[P′_{i}, E : Γ_{i} ⊢ e′ : [Int/α]τ′]
P_{b}[P′_{b}, E : Γ_{b} ⊢ e′ : [Bool/α]τ′]

und schreiben kurz τ_{i} = [Int/α]τ′ und τ_{b} = [Bool/α]τ′. Aus der Forderung α rocc τ′ folgt fschm(τ_{i}) ∩ fschm(τ_{b}) = ∅ also mit der eindeutigen Zerlegung von Werten cval(τ_{i}) ∩ cval(τ_{b}) = ∅.

Wir führen nun einen Widerspruchsbeweis. Sei angenommen die Auswertung von e konvergiert. Es gäbe also einen Wert v, so daß e ↦_{v}^{∗} v gilt. Nach den Voraussetzungen muß sich diese Auswertung wie folgt zusammensetzen :

e ≡ E[< e′ >] ↦_{v}^{∗} E_{v}[< e′′ >] ↦_{v}^{∗} E_{v}[v′] ↦_{v}^{∗} v

Wobei das Mittelstück nach durch Anwendung der Regel

\frac{e′′ ↦_{v}^{∗} v′}{E_{v}[e′′] ↦_{v}^{∗} E_{v}[v′]}

zusammengesetzt war. Nun gilt die Subjektreduktion und aus e′′ : τ_{i} und e′′ : τ_{b} folgt v′ ∈ cval(τ_{1}) ∩ cval(τ_{b}) aus diesem Widerspruch folgt der Satz.

Lemma 5.1.2 (leere Constraints) In einer strikt auswertenden Sprache mit Überladung gilt folgende Aussage. Sei eine Instanz für eine überladene Funktion o : ∀\overline{α}.C ⇒ τ → τ′ gegeben und ein dazu passender Argumentwert v ∈ cval(τ). Falls nun eine Überladungseinschränkung o′ : τ_{1} → τ_{2} ∈ C zu obiger Instanz existiert, so daß eine Typvariable α im Typ des Argumentwertes v verzichtbar ist jedoch im Argumentstyp der Einschränkung o′ relevant ist, (formal: ⊢ v : ∀Sτ ∧ α ∉ dom(S) ∧ α rocc τ_{1}), dann kann geschlossen werden, daß der Funktionsaufruf ov entweder divergiert oder niemals der Aufruf von o′ ausgeführt wird welcher zur Einschränkung gehört. In keinem der Fällen ist also eine Instanzauswahl für die Einschränkung o′ nötig. In solch einer Aufrufsituationen wird die Einschränkung o′ : τ_{1} → τ_{2} leer genannt. Beweis:

Zum Beweis des Satzes können wir das Programm e ≡ inst o = e′ in E[ov] als gegeben ansehen, denn vor Aufruf der Funktion o muß die entsprechende Instanz definiert sein. Wir untersuchen nun die Situationen welche in einem getypten Programm auftreten können, also nehmen wir eine Herleitung P : ⊢ e : τ als gegeben an. Daraus folgen die zwei Beweisteile welche uns interessieren. Die Typisierung des Funktionsaufrufs

P[P′, inst o = e′ in E[ ] : Γ′ ⊢ ov : Sτ′] (1)

5.2. DAS LOGISCHE SYSTEM O_{2} 125

wobei uns die Voraussetzungen mitteilen, daß die quantifizierte Typvariable α nicht in der Typothese auftritt α ∉ tv(Γ′). Außerdem muß noch die Instanzdeklaration typisierbar sein, also erhalten wir den Beweisteil

P[P′′, inst o = [ ] in E[ov] : Γ′′ ⊢ e′ : ∀\overline{α}.C ⇒ τ → τ′] (2)

Also gilt auch hier α ∉ tv(Γ′′). Die Präsenz der Überladungseinschränkung o′ : τ_{1} → τ_{2} ∈ C besagt, daß ein Aufruf der überladen Funktion o′ in der Instanzdefinition e′ auftritt. Damit läßt sich ein Beweisteil aus der Typisierung des Instanzkörpers e′ entnehmen

P′′[P_{3}, E′[o′[ ]] : Γ_{3} ⊢ e′′ : τ_{1} (3)

Nun wollen wir untersuchen wie die Auswertung des Redex ov abläuft. Zuerst wird eine Instanzauswahl durchgeführt, so daß e′v der neue Redex ist. Nachdem ⊢ v : ∀Sτ ∧ α ∉ dom(S) gibt es also wegen (1) eine Herleitung P_{4} : Γ_{4} ⊢ e′v : ∀α.Sτ′. Aus (2) und (3) folgt weiter eine Teilherleitung P_{4}[P_{5}, E[E′[o′[]]] : SΓ_{3} ⊢ e′′ : Sτ_{1}] mit α rocc τ. Damit sind die Voraussetzungen des obigen Satzes erfüllt und wir können schließen, daß bei der Reduktion von e′v entweder e′′ nie reduziert wird oder e′v divergiert. Das ist die Aussage des zu zeigenden Satzes : Bei Auswertung von ov wird entweder o′ nie aufgerufen oder ov divergiert.

5.2 Das logische System O_{2}

Im vorigen Abschnitt haben wir gesehen, daß die Argumente eines algebraischen Typkonstruktors entweder relevant oder verzichtbar sind. Wir wollen diese Eigenschaften jetzt nutzen um eine neue Sichtweise auf die algebraischen Datentypen zu gewinnen. Wir wollen nun die Typkonstruktoren als konstruktive Bausteine der Typen durch relevante Typkerne als konstruktive Bausteine der Typen ersetzen.

Definition. (relevante Typkerne) Sei ein algebraischer Datentyp A = (T , a, D, arg, t) gegeben und eine Striktheitsmarkierung M = (C, r, d) zu den Typkonstruktoren T . Die Menge der relevanten Typkerne sei K(A, M) genannt und ist gegeben durch alle Kerne über Typkonstruktoren k ∈ K(T ), so daß alle Pfade im Kern relevant sind also ∀p ∈ pth(k).k ↓ p.

Das heißt ein relevanter Kern ist aus Typkonstruktoren so zusammengesetzt, daß der Definitionsbereich eines Kerns k nur relevante Pfade enthält. Im Hintergrundkapitel wurde definiert wie sich aus einem Kern k und einer Sequenz von Typen \overline{τ} ein Typ k\overline{τ} zusammensetzen läßt. Besetzt man relevante Stellen mit relevanten Typkernen so erhält man wieder einen relevanten Typkern. Daraus läßt sich eine Ordnung auf Typkernen definieren:

k <^{k} k′ gdw pth(k) ⊆ pth(k′) ∧ ∀p ∈ pth(k).k.p = k′.p

Es ist noch eine Relation #^{r} zu definieren um die Verschiedenheit im Kern auszudrücken für den Fall, daß es einen gemeinsamen Pfad gibt der verschieden Markiert ist.

k#^{r}k′ gdw ∃p ∈ pth(k) ∩ pth(k′).k.p ≠ k′.p

Der relevante Kern eines Typs ist gegeben durch alle über relevante Pfade erreichbaren Typkonstruktoren (also der größte relevante Kern welcher in einem Typ an der Wurzel sitzt).

k <^{r} τ gwd ∀p ∈ pth(τ) τ ↓ p ⟹ k.p = τ.p

Damit ist es nun möglich die Kernverschiedenheit auf Typen zu erweitern.

τ#^{r}τ′ gdw k <^{r} τ ∧ k′ <^{r} τ′′ ∧ k#^{r}k′

Wir können nun auch die Kernordnung auf Typen erweitern.

τ <^{k} τ′ gdw k <^{r} τ ∧ k′ <^{r} τ′ ∧ k <^{k} k′

Die Beziehung τ <^{k} τ′ bedeutet, daß der Typ τ′ spezifischer oder kernüberdeckend relativ zu Typ τ ist. Ziel dieser Untersuchung von relevanten Kernen ist der folgende Satz welcher aus der Kernverschiedenheit der Typen die Disjunktheit der zugehörigen Wertmengen folgert.

Lemma 5.2.1 (disjunkte Wertmengen) Seien zwei Typen τ und τ′ gegeben, dann gilt die Folgerung :

τ#^{r}τ′ ⟹ cval(τ) ∩ cval(τ′) = ∅

Beweis: Aus der Kernverschiedenheit der relevanten Typen folgt die Existenz eines Pfades p welcher zum einen relevant in beiden Typen ist τ ↓ p ∧ τ′ ↓ p und zum anderen die Typen an diesem Punkt unterscheidet τ|p = T \overline{τ} ≠ T′\overline{τ}′ = τ′|p. Angenommen es gäbe einen Wert v ∈ cval(τ) ∩ cval(τ′) wegen der eindeutigen Zerlegung von v gibt es also ein Schema, so daß die Darstellung v = s\overline{v} möglich ist. Weiter muß für das Schema s ∈ fschm(τ) ∩ fschm(τ′) gelten. Dann gäbe es wegen der Relevanz von p einen Pfad p′ in dem Schema s, so daß der Kern s.p′ sowohl in fschm(T \overline{τ}) als auch in fschm(T′\overline{τ}′) enthalten wäre. Dieser Widerspruch hebt die Annahme auf □.

Durch dieses Lemma haben wir die Möglichkeit aus syntaktischen Betrachtungen die Wohldefiniertheit von überladenen Funktionen zu schließen. Seien zwei Instanzen o : τ_{1} → τ_{1}′ und o : τ_{2} → τ_{2}′ für die überladene Funktion o gegeben, so muß für die Argumenttypen nur τ_{1}#^{r}τ_{2} gelten damit die Argumentbereiche verschieden sind und also bei dem Zusammenfassen der beiden Instanzen eine wohldefinierte überladene Funktion definiert wird. Wir definieren nun ein neues logisches System O_{2} durch Ersetzung der alten Instanzregel (INST) durch eine neue Regel.

(INST)^{2} \frac{Γ \ o ⊢ e : σ_{i}  Γ.o : σ_{i} ⊢ e′ : τ  (∀o : σ′_{i} ∈ Γ.σ_{i}#^{i}σ′_{i})}{τ ⊢ inst o = e in e′ : τ}

Die wichtigste Änderung in dieser neuen Regel ist die Ersetzung des alten Instanztyps σ_{T} durch den neuen Instantztyp σ_{i} wobei der neue Typ die Form

σ_{i} ::= ∀\overline{α}.C ⇒ τ → τ′

hat und #^{i} ist die Wohldefiniertheitsbeziehung für zwei Instanztypen.

σ_{i}#^{i}σ_{i} gdw σ_{i} ≡ ∀\overline{α}.C ⇒ τ_{1} → τ_{2} ∧ σ′_{i} ≡ ∀\overline{β}.C′ ⇒ τ_{1}′ → τ_{2}′ ∧ τ_{1}#^{r}τ_{1}′

Die alten syntaktischen Restriktionen für Instanztypen des System O

\begin{aligned}σ_{T} & = & T α_{1} ... α_{n} → τ & (tv(τ) ⊆ \{α_{1}, …, α_{n}\}) \\ & | & ∀α.π_{α} ⇒ σ′_{T} & (tv(π_{α}) ⊆ tv(σ′_{T})). \end{aligned}

wurden also aufgehoben. Die Restriktion der Form T α_{1} ... α_{n} für Argumenttypen ist völlig aufgehoben, auch die Restriktionen über die Verwendung der Typvariablen entfallen.

Man beachte, daß in der linken Prämisse Γ \ o ⊢ e : σ_{i} der Regel (INST)^{2} alle Instanzen der überladenen Funktion entfernt werden (in Notation Γ \ o). Durch diese Eigenschaft des logischen Systems ist die Nutzung von rekursiver überladener Polymorphie ausgeschlossen. Das führt zu einer Eigenschaft der Instanztypen in einer Typothese

o : σ_{i} ∈ Γ∧σ_{i} ≡ ∀\overline{α}.C ⇒ τ → τ′ ⟹ o : τ_{1} → τ_{2} ∉ C (keine rekursiven Instanzen)

Gleichzeitig wird die Ausdrucksstärke der Sprache kaum eingeschränkt, denn rekursive Funktionsdefinitionen sind in der let Anweisung möglich.

5.3 Musterpassung auf Typebene

In dem Hintergrundkapitel wurden bereits algebraische Datentypen eingeführt. Um die algebraischen Datentypen in Kalkülen zu verwenden, wurden die Konstruktoren und Destruktoren definiert. Wir wollen hier nocheinmal einen Blick auf algebraische Datentypen werfen, aber nicht aus Richtung der Kalküle sondern im Stil des funktionalen Programmierens. Im funktionalen Programmieren sind algebraische Datentypen durch die Datenkonstruktoren und die Musterpassung dem Programmierer zur Verfügung gestellt. Wir benutzen diese Darstellung, da sich daraus in Analogie ein Kalkül mit expliziter Überladung ergibt.

Musterpassungen lassen sich als partielle Destruktoren auffassen. Ein Ausdruck zur Musterpassung wird als λp_{1} ⇒ e_{1} … p_{n} ⇒ e_{n} notiert wobei p die Muster benennt. Ein Muster ist ein Datenwert in dem Termvariablen einmalig auftreten können. Formal ist die Menge der Muster wie folgt definiert :

pat(T \overline{τ}) =^{def} \{D\overline{p} | \overline{p} ∈ pat(\overline{τ}) 1 < i < j < a(T) ⟹ v(\overline{p}.i) ∩ v(\overline{p}.j) = ∅\} ∪ V ar

wobei V ar die Menge der Termvariablen (x, x′, …) ist und v(p) die Menge der verwendeten Termvariablen zu dem Muster p angibt. Nun definieren wir Musterpassung als eine Abbildung v ⊲^{p} p ↦ S wobei v ein Datenwert ist (auch Argument der passung genannt), p ist ein Muster und S ist eine Substitution von Termvariablen durch Datenwerte. Der Datenwert wird dabei in Teile zerlegt und diese Teile an die Termvariablen des Musters gebunden. Die Musterpassung ist durch strukturelle Induktion wie folgt definiert :

v ⊲^{p} x ↦ (x ↦ v) wobei x ∈ V ar
D\overline{v} ⊲^{p} D\overline{p} ↦  ⋃_{i=1}^{|arg(D)|} S_{i}
wobei \overline{v}.i ⊲^{p} \overline{p}.i ↦ S_{i}
sonst ↦  F ehlschlag

Natürlich muß der Datenwertes v und das Musters p einen gemeinsamen Typ besitzen d.h. v ∈ cval(τ) ∧ p ∈ pat(τ). Wir sagen, daß der Wert v zu dem Muster p paßt, wenn die Musterpassung nicht fehlschlägt (kurz:v ⊲^{p} p ↓). Sei eine Menge von Mustern P = {p_{1}, …, p_{n}} gegeben, so daß ein gemeinsamer Typ τ für alle Muster existiert (p_{i} ∈ pat(τ)). Für solche Mengen von Mustern gibt es zwei interessante Eigenschaften :

P ist eine erschöpfende Menge von Mustern.

∀v ∈ cval(τ) ∃p ∈ P. v ⊲^{p} p ↓

d.h. für jeden Datenwert mit entsprechendem Typ gibt es passende Muster in der Menge der Muster.

P ist eine nicht überlappende Menge von Mustern:

∀v ∈ cval(τ) |{p | p ∈ P, v ⊲^{p} p ↓}| ≤ 1

d.h. Falls es zu einem Datenwert ein passendes Muster in der Menge gibt, dann ist es das einzige passende Muster.

Nun fügen wir die Musterpassung in einen Kalkül ein durch eine weitere δ-Regel.

(λp_{1} ⇒ e_{1} … p_{n} ⇒ e_{n})v ⟶^{δ} Se_{i} gdw v ⊲^{p} p_{i} ↦ S

Im Licht dieser Reduktion erhalten die Eigenschaften einer Mustermenge P = {p_{1}, …, p_{n}} eine Bedeutung für Programme. Ein Ausdruck mit Musterpassung ist deterministisch, wenn es höchstens ein passedes Muster zu jedem Datenwert gibt d.h. wenn P nicht überlappend ist. Ein Ausdruck mit Musterpassung kann nicht fehlschlagen wenn es zu jeden richtig getypten Datenwert passende Muster gibt d.h. wenn P erschöpfend ist. Ein Ausdruck mit Musterpassung stellt eine wohldefinierte Funktion dar gdw für jeden Datenwert genau ein Resultat existiert d.h. wenn P erschöpfend und nicht überlappend ist.

Bisher wurde Musterpassung auf der Ebene der Terme erläutert. Nun folgt die Schlüsselbeobachtung dieses Abschnitts; Überladung kann als eine Form der Musterpassung auf der Ebene der Typen angesehen werden. Typen haben fast die selbe Struktur als Muster für Terme da sie aus Typkonstruktoren und Typvariablen zusammengesetzt sind. Der Unterschied zwischen Termmustern und Typen besteht darin, daß die Typvariablen mehrfach in Typen auftreten können während Termvariablen nur einfach auftreten können. Desweiteren kann eine überladene Funktion undefiniert sein für manche Argumenttypen, also muß die Menge der Typmuster nicht erschöpfend sein. In der Praxis wird oft auch für Termmuster die Forderung nach erschöpfender Überdeckung aufgeweicht. Daraus resultiert dann die Existenz von partiellen Funktionen auch ohne Divergenz.

Allerdings erwarten wir immer noch, daß überladene Funktionen wohldefiniert sind, also eine eindeutige Abbildung von Argumenten auf Resultate darstellen. Also benötigen wir einen Begriff von Nichtüberlappung, der zu Mengen von Typmustern paßt. Auf den ersten Blick könnte dies der Begriff der Nichtunifizierbarkeit von Typen sein. Wir hatten allerdings bei der Definition des logischen Systems festgestellt, daß die relevanten Typkerne wesentlich für die Wohldefiniertheit einer überladenen Funktion sind. Auf Grund dieser Beobachtung definieren wir nun Musterpassung auf der Typebene τ ⊲^{t} τ′, dabei sollen sowohl der anzupassende Typ τ als auch das Muster τ′ aus der selben Typgrammatik gebildet werden. Wir definieren

τ ⊲^{t} τ′ ↦ U \begin{cases}wenn τ′ <^{r} τ & U = mgu(τ, τ′) \\ sonst & Fehlschlag \end{cases}

Also ist die Typpassung genau dann erfolgreich, wenn der allgemeinste Unifikator U der Typen τ und τ′ existiert unter der Voraussetzung, daß das Argument τ kernüberdeckend relativ zu τ′ ist. Analog ist eine Musterpassung auf Termebene nur dann möglich, wenn der Argumentwert soweit ausgewertet ist, daß er das Muster überdecken kann. Mit der Musterpassung auf Typen können wir nun den Kalkül F_{o} mit expliziter Überladung darstellen.

5.3.1 Der explizite Überladungskalkül F_{O}

Der Kalkül F_{o} ist explizit getypt und eine Erweiterung des System F. Da die Musterpassung auf der Typebene hinzugefügt wurde, kann dies als Musterpassung zweiter Stufe angesehen werden. Man beachte, daß der Kalkül nur wohldefinierte Musterpassung zuläßt, indem für die Ausdrücke Λτ_{1} ⇒ e_{1} … τ_{n} ⇒ e_{n} die Kernverschiedenheit der Muster gefordert wird.

Terme  e ::= x | λx : τ.e | ee′ |

Λτ_{1} ⇒ e_{1} … τ_{n} ⇒ e_{n} | eτ ( wobei i ≠ j ⟹ τ_{i}#^{r}τ_{j})

Reduktion (β) (λx : τ.e′)e ⟼ e′[e/x]
(δ) (Λτ_{1} ⇒ e_{1} … τ_{n} ⇒ e_{n})τ ⟼ e

wobei e = \begin{cases}Se_{i} gdw τ ⊲ τ_{i} ↦ S \\ W rong sonst \end{cases}

5.3.2 Andere Ansätze

Hier werden nun die Resultate aus der Literatur besprochen welche sich auch mit der Musterpassung auf Typebene [LM91, RH95, ACPP91] oder mit Überladung in Kalkülen [CGL93, Tsu92, Tsu94, Tsu95] beschäftigen.

Die Ansätze von Abadi et. al. [ACPP91] und Leroy/Mauny [LM91] beschäftigen sich mit einer Spracherweiterung welche dynamische Typisierung genannt wird. Diese Idee besagt im Kern, daß es wünschenswert wäre eine Mischung von statischer und dynamischer Typprüfung in einer Sprache zu haben. Die Aufweichung der statischen Typprüfung geschieht durch die Einführung eines neuen Typs dyn und eines Konstruktors dynamic welcher Werte als ein Tupel von Term und Typ zusammensetzt, die dynamische Typprüfung geschieht durch die typecase-Anweisung welche eine Musterpassung sowohl auf Typebene als auch auf Termeben enthält. Die Behandlung des typecase führt zu einer Vielfalt von Möglichkeiten.

τ .. = … | dyn
e ::= … | dynamic(e : τ) | e. p_{1} : τ_{1} ⇒ e_{1} … p_{n} : τ_{n} ⇒ e_{n} | Wrong
(dynamic) \frac{Γ ⊢ e : τ}{Γ ⊢ dynamic(e : τ) : dyn}

In Abadi et. al. wird ein logisches System und die operationale Semantik für dynamische Typisierung gegeben. Das Grundsystem enthält keine Polymorphie und die Typinferenz fehlt in den Betrachtungen. Das Fehlen der Polymorphie führt zu der Einschränkung, daß der Typ eines typecase-Ausdrucks konstant sein muß. Abadi et. al. schlagen folgende Regel für die Verwendung des typecase vor :

Γ ⊢ e_{sel} : dyn
∀i. ∀S. dom(S) ⊆ tv(τ_{i}) Γ.x : Sτ_{i} ⊢ Se_{i} : τ
Γ ⊢ e_{else} : τ
Γ ⊢ typecase e_{sel}. x : τ_{1} ⇒ e_{1} … x : τ_{n} ⇒ e_{n} else ⇒ e_{else} : τ

Man beachte, daß eine typecase-Anweisung immer einen else-Zweig besitzt. In der operationalen Semantik kann also ein typecase nicht bei Fehlschlag der Musterpassung zu einem Wrong auswerten, so daß aus dem Beweis der Subjektreduktion für den Kalkül (also (e ⟶^{∗} v ∧ ⊢ e : τ) ⇒ ⊢ v : τ) auch gleich als Korollar die semantische Korrektheit aus der Nichttypisierbarkeit des Wrong folgt (also (e ⟶^{∗} v ∧ ⊢ e : τ) ⇒ v ≠ Wrong). Der Satz der semantischen Korrektheit wird bei Abadi et. al. auch noch mit einer Idealsemantik bewiesen. Das Papier schließt mit Ideenskizen um Polymorphie, abstrakte Datentypen und “kinded” Typvariablen in den Ansatz einzuführen. Der Ansatz von Leroy/Mauny erweitert die Ausdruckskraft und die operationale Semantik des typecase in 4 Punkten:

Termmuster Anstatt der Variablen x für jeden Zweig der Unterscheidung x : τ ⇒ e werden Termmuster p zugelassen.

gemischte Muster Statt einer reinen Musterpassung nur mit dynamischen Mustern p : τ wird gemischte Musterpassung zugelassen. Der Ausdruck dynamic(e : τ) wird also wie ein zusätzlicher algebraischer Datenkonstruktor behandelt. Damit wird also das typecase als erweiterte Musterpassung auf Termebene aufgefasst.

Polymorphie Die von Leroy/Mauny vorgeschlagene typecase-Anweisung kann Polymorphie behandeln. Die Typvariablen welche dabei in Typmustern auftreten, können nicht bei der Musterpassung gebunden werden. Also ist bei den beiden gegebenen Mustern List α ⇒ … List Int ⇒ … das Muster List α spezifischer da die Typvariable α nicht gebunden werden kann während das Muster List Int allgemeiner ist, da eine Argumentwert vom Typ ∀α.List α intantiiert werden kann.

Existenztypen Um auch noch die Bindung von Typvariablen in der Musterpassung zu behandeln wird eine gemischte Quantifizierung der Variablen des Typmusters eingeführt. Die allgemeine Form des typecase hat bei Leroy/Mauny dann die Form :

\begin{aligned}e & ::= & … | ΛQ_{1}p_{1} : τ_{1} ⇒ e_{1} … Q_{n}p_{n} : τ_{n} ⇒ e_{n} \\ Q & ::= & ϵ | ∀α.Q | ∃α.Q \end{aligned}

Damit ist es zum Beispiel möglich die allgemeine Form der dynamischen Funktionsanwendung zu formulieren.

Λ ∃α.(f, x) : (α → Int × α) ⇒ fx

Die operationale Semantik dieser typecase-Anweisung ist jedoch sehr komplex. Bindungen der existentiell quantifizierten Typvariablen müssen in einer Closure mitgeführt werden. Bei der Durchführung der Musterpassung ist zusätzlich zur Passung auf Termebene noch ein Unifikationsproblem mit gemischten Quantoren auf der Typebene zu lösen. In dem Papier werden Beispiele zur Verwendung der typecase-Anweisung gegeben und Hinweise zu dessen Implementierung gegeben, Typinferenz und eine denotationale Semantik fehlen jedoch.

In Bezug auf den Kalkül F_{o} und seine Verwendung in der ⇝^{rc}-Übersetzung kann festgestellt werden, daß auch eine Mischung der Musterpassung auf Typ- und Termebene wie im typecase möglich wäre. Die Methode, operational die semantische Korrektheit zu beweisen, kann nicht übernommen werden da in F_{o} ein Fehlschlag immer zu Wrong führt. Die Einfügung von algebraischen Datentypen wurde von keinem der Ansätze behandelt, nur Listen traten in beiden Papieren auf. Der Begriff der Relevanz ist also eine Neuerung. Eine weitere Linie von Ansätzen ist in Zusammenhang des Kalküls λ& in den Arbeiten von Castagna/Ghelli/Longo [CGL93] und Tsuiki [Tsu92, Tsu94, Tsu95] zu finden. Diese Ansätze beschäftigen sich mit dem Einfügen von Überladung in den Lambdakalkül und der Auswahl der Überladungsinstanzen. In Castagna et. al. wird für die Instanzauswahl zur Laufzeit der Begriff “late binding” aus der Objektorientierung übernommen, dem gegenüber steht eine frühere Instanzauswahl zum Teil schon bei der Typisierung “early binding” genannt. In der Arbeit von Castagna et. al wir eine einfache Erweiterung des Lambdakalküls untersucht

\begin{aligned}e & ::= … | & e&e′ \\ τ & ::= … | & \{τ_{1} → τ_{1}′, τ_{2} → τ_{2}′, … \} \end{aligned}

Der Kalkül ist explizit getypt enthält, aber keine parametrische Polymorphie. Statt dessen wird eine gegebene Subtypordnung angenommen. Der Ausdruck e&e′ sammelt die Instanzen einer überladenen Funktion auf. Die Reduktion

(e_{1}& … &e_{n})e ⟶ e_{i}e

ist damit erklärt, daß der Argumentterm e den Typ τ habe und die Funktion mit (e_{1}& … &e′_{n}) : {τ_{1} → τ_{1}′, …, τ_{n} → τ′_{n}} typisiert ist. Die Subtypbeziehung τ ≤ τ_{i} begründet die Auswahl der Instanz e_{i}. Weiter wird in dem System die Eindeutigkeit dieser Auswahl gefordert. Aus der Typisierung (e_{1}& … &e′_{n}) : {τ_{1} → τ_{1}′, …, τ_{n} → τ′_{n}} läßt sich die Eindeutigkeitsforderung formulieren; wenn für ein i die Subtypbeziehung τ ≤ τ_{i} gilt, dann gibt es einen minimalen Typ τ_{j} = min{τ_{i} | τ ≤ τ_{i}}. Durch Einführung von expliziten Typwandlungen c_{τ}

\frac{e : τ′ ≤ τ}{c_{τ}(e) : τ}

kann zu einem früheren Zeitpunkt die Instanzauswahl ausgeführt werden. Mit Typwandlungen c_{τ} und dem Auswahlmechanismus zur Auflösung der Überladung (e_{1}& … &e_{n}) erhält man die Ausdruckskraft von Musterpassung auf Typebene. Falls man die Subtypordnung ≤ durch die Instanzbeziehung von Typen oder die Kernüberdeckungsbeziehung ersetzt läßt sich der F_{o} Ansatz vergleichen. Vielversprechend ist die Modellierung des λ&-Kalküls mit partiellen Äquivalenzrelationen, dies könnte auch für das System O_{2} und F_{o} zu einem guten Modell möglicherweise mit Parametrizität führen. Der Untersuchung des λ&-Kalküls fehlt aber die Einbettung von Polymorphie und Betrachtung der Typinferenz.

Der Ansatz von Tsuiki ist es die Eindeutigkeitsforderung von λ& aufzuheben. Der Überladungsoperator & wird durch einen merge-Operator ⊗ ersetzt und es ergibt sich eine neue Reduktion :

(e ⊗ e′)e′′ ⟶ (ee′′) ⊗ (e′e′′)

Diese Reduktion findet statt bei folgender Typisierungssituation e : τ → τ_{r}, e′ : τ′ → τ_{r}, e′′ : τ′′ wobei beide Subtyprelationen erfüllt seien τ′′ ≤ τ, τ′′ ≤ τ′. Bei der Anwendung einer überladenen Funktion werden also alle anwendbaren Instanzen ausgewählt. Erst bei Basistypen (also z.B. e : Int, e′ : Bool) wird der erste Term ausgewählt.

e ⊗ e′ ⟶ e

Dieser Kalkül ist mit einer kategorischen Semantik fundiert worden. Ziel der Arbeit ist es Objektorientierung in Kalkülen zu modellieren. So wird auch die Einbettung von Records und generischen Funktionen untersucht. Die generischen Funktionen benutzen eine Form von gebundener Polymorphie um die Erweiterung von Objekten und Klassen bei der Vererbung zu modellieren.

Zusammenfassend läßt sich sagen, daß Untersuchungen von Überladung meist zur Modellierung von Aspekten der Objektorientierung führen. Keiner der untersuchten Ansätze beschäftigt sich allerdings mit Typinferenz und der Instanzauswahl zur Übersetzungszeit. Dies sind jedoch zwei wesentliche Zutaten, um Überladung in Programmiersprachen einfach benutzbar anzubieten und effizient implementieren zu können.

5.4 Operationale Semantik für Überladung

Es werden zwei Übersetzungen des System O_{2} in den F_{o}-Kalkül gegeben. Die zwei Resultate der Übersetzung unterscheiden sich in dem Zeitpunkt zu dem die Codeselektion für überladene Funktionen ausgeführt wird. Mit diesen Mitteln kann ein naheliegender Satz formalisiert werden. Bei Terminierung eines der beiden Resultatsprogramme folgt auch die Terminierung des anderen Programms und beide Programme gelangen zu den gleichen Ergebnissen. Daraus folgt, daß die Implementierung von Überladung in einer Programmiersprache zu keinem zusätzlichen Laufzeitaufwand führen muß.

In dem vorigen Abschnitt wurde der Kalkül F_{o} für explizite Überladung dargestellt, welcher eine operationale Semantik durch Musterpassung auf Typebene erhielt. In diesem Abschnitt werden wir den Kalkül F_{o} benutzen um der implizit getypten Sprache System O_{2} eine operationale Semantik zu geben. Diese Semantik wird in Form einer Übersetzung von impliziten Ausdrücken nach expliziten Ausdrücken dargestellt.

Die Übersetzung nimmt einen getypten Ausdruck des System O_{2} erzeugt einen Ausdruck des System F_{o}. Technisch wird eine Typisierungsherleitung aus dem System O_{2} mit Hilfe einer Sammlung von Überladungsinstanzen I in einen F_{o}-Ausdruck umgeformt. Die Übersetzungsaussagen haben die folgende Form :

Γ ⊢ e : σ ⇝^{cr} e′, I

wobei e ein getypter Ausdruck des System O_{2} ist und ⇝^{r} die Übersetzung zur Laufzeitauswahl anzeigt, so daß in diesem Fall der Resultatesterm e′ ein F_{o}-Ausdruck ist. Nur die Instanzauswahl zur Laufzeit benötigt Musterpassung auf Typebene also wird bei der ⇝^{c}-Übersetzung (der Auswahl zur Übersetzungszeit) ein Resultatsterm e′ des System F erzeugt. I sammelt alle Instanzdefinition für überladene Funktionen auf. Die Instanzsammlung I hat die Struktur einer Abbildung I : O × T y → F_{o} wobei O die Menge der überladenen Namen ist und T y die Menge der Typen ist. Das heißt bei Definiertheit der Funktion I für das Argument (o, τ) gibt es eine Instanz der überladenen Funktion o für Argumente des Typs τ. Diese Instanz ist dann durch den Term I(o, τ) = e definiert. Die Übersetzung ist in zwei Phasen geteilt. In der ersten Phase wird eine Typherleitung in einem F_{o}-Term umgewandelt. In der ersten Phase werden auch alle Instanzdefinitionen für überladene Funktionen in die Instanzsammlung I eingefügt. Dieser Sammlungsschritt geschieht für jede Anwendung der (INST)^{2}-Regel in der Herleitung.

(INST)^{rc}

Γ ⊢ e_{1} : σ_{i} ⇝ e′_{1}, I

dom(I(o, −)) = {τ_{1}, …, τ_{m}} für σ_{i} ≡ ∀\overline{α}.C ⇒ τ → τ′

I′ =^{def} (I | (o, τ) ↦ e′_{1})

Γ.o : σ_{i} ⊢ e_{2} : τ′′ ⇝^{rc} e′_{2}, I′

Γ ⊢ inst o = e_{1} in e_{2} : τ′′ ⇝^{rc} e′_{2}, I′

In der zweiten Phase werden aus dieser Sammlung I dann die überladenen Funktionen als F_{o}-Terme codiert. Die Übersetzungsschritte für Funktionen und let-Ausdrücke bergen keine besonderen Informationen da es sich um die Ausdruckmittel jedes Lambdakalküls handelt

(I →)^{rc}, (E →)^{rc} Identitätsübersetzung

(LET)^{rc}  \frac{Γ ⊢ e_{1} : σ ⇝ e′_{1}, I Γ.u : σ ⊢ e_{2} : τ ⇝ e′_{2}, I}{Γ ⊢ let u = e_{1} in e_{2} : τ ⇝ (λu.e′_{1})e′_{2}, I}

Bei der Übersetzung der Namen wird auf die Benutzung der (T AUT)-Regel in der Typherleitung Bezug genommen. Die eindeutigen Namen werden bei der Übersetzung unverändert übernommen. Bei der Übersetzung der überladenen Namen treten die Unterschiede zwischen der beiden Übersetzungsstrategien zu Tage. Bei der Instanzauswahl zur Laufzeit ⇝^{c} werden nur die Namen der Überladungseinschränkungen übersetzt, nämlich in eine Anwendung oτ der überladenen Funktion auf einen Typ so daß bei Reduktion dieses Ausdrucks die Instanzauswahl zur Laufzeit ausgeführt wird. Bei der Instanzauswahl zur Übersetzungszeit ⇝^{r} müssen für Überladungsinstanzen und Überladungseinschränkungen neue Name erzeugt werden. Die Namen o^{τ} welche sich auf Instanzen beziehen werden in der zweiten Phase gebunden. Die Namen o^{c} beziehen sich auf die Überladungseinschränkungen und werden bei der Einführung von Quantoren gebunden.

eindeutige Namen  Γ.u : σ ⊢ u : σ  ⇝^{rc} u, I
Überladungsinstanzen  Γ.o : σ_{i} ⊢ o : σ_{i}  ⇝^{c} o^{τ}, I
mit σ_{i} ≡ ∀\overline{α}.C ⇒ τ → τ′ und o^{τ} eindeutiger Name zu o : σ_{i}
Überladungseinschränkungen Γ.o : τ → τ′ ⊢ o : τ → τ′ ⇝^{r} oτ, I
⇝^{c} o^{c}

mit o^{c} eindeutiger Name zur Einschränkung o : τ → τ′

Die Behandlung der Quantoren bilden den Kern der Übersetzung. Für die ⇝^{r}-Über-setzung wird bei Einführung der Quantoren eine Abstraktion über die gebunden Typvariablen codiert, und entsprechend bei der Elimination der Quantoren werden die zur Instantiierung benutzten Typargumente S\overline{α} an die Funktion übergeben.

Im Gegensatz dazu wird für die ⇝^{c}-Übersetzung bei der ∀-Einführung über die Überladungseinschränkungen abstrahiert. Für die ∀-Elimination wird eine Reihe von ausgewählten Instanzen \overline{e} bei der Erfüllung der Einschränkungsnebenbedingung erzeugt. Diese ausgewählten Instanzen \overline{e} werden dann an die Funktion übergeben. Die Reihe der Instanzen wird durch die (SET)-Regel erzeugt.

(∀I)^{rc}  \frac{Γ.C ⊢ e : σ ⇝^{rc} e′, I}{\begin{matrix}Γ ⊢ e : ∀\overline{α}.C ⇒ σ & ⇝^{r} & Λ\overline{α}.e′ \\ ⇝^{c} & λo_{1}^{c} … o_{n}^{c}.e′ \\ wobei C = \{o_{1} : τ_{1} → τ′_{1}, …, o_{n} : τ_{n} → τ′_{n}\} \end{matrix}}

(∀E)^{rc}  \frac{Γ ⊢ e : ∀\overline{α}.C ⇒ σ ⇝^{rc} e′, I Γ ⊢ SC ⇝^{c} \overline{e}}{\begin{aligned}Γ ⊢ e : Sσ & ⇝^{r} & e′S\overline{α} \\ & ⇝^{c} & e′\overline{e} \end{aligned}}

(SET)^{c} \frac{Γ ⊢ o : τ_{1} → τ_{1}′ ⇝^{c} e_{1}, I … Γ ⊢ o : τ_{n} → τ′_{n} ⇝^{c} e_{n}, I}{Γ ⊢ o : τ_{1} → τ_{1}′ … o : τ_{n} → τ′_{n} ⇝^{c} e_{1} … e_{n}}

In der zweiten Phase der Übersetzung wird die Sammlung der Instanzen I benutzt, um die überladenen Funktionen zu definieren. Bei dieser zweiten Übersetzungsphase werden die Einträge aus der Instanzensammlung entfernt bis diese leer ist. Damit ist dann die Übersetzung beendet.

Für die Übersetzung zur Laufzeitauswahl ist die zweite Phase der Punkt an dem Musterpassung auf Typebene benutzt wird. Denn für jede überladene Funktion gibt es eine Musterpassung in welcher für jeden Argumenttyp die passende Instanz ausgewählt wird.

Γ ⊢ e : σ ⇝^{r} e′, I wobei dom(I(o, −)) = {τ_{1}, …, τ_{n}}

⇓

Γ ⊢ e : σ ⇝^{r} (λo.e)(Λτ_{1} ⇒ I(o, τ_{1}) … τ_{n} ⇒ I(o, τ_{n})), (I | (o, −) ↦ undef)

Die zweite Phase der Übersetzung ⇝^{c} hat das Ziel, die Namen o^{τ} mit den entsprechenden Instanzkörpern zu belegen. Der aufmerksame Leser stellt sicherlich fest, daß diese Operation auch bei der Behandlung der (INST)^{2}-Regel ausgeführt werden kann. Also kann die Übersetzung mit Instanzauswahl auch in einer Phase ausgeführt werden.

Γ ⊢ e : σ ⇝^{c} e′, I

⇓

Γ ⊢ e : σ ⇝^{c} (λo^{τ}.e′)I(o, τ), (I | (o, τ) ↦ undef)

Für beide Übersetzungstrategien wird die zweite Phase solange ausgeführt, bis die Instanzensammlung leer ist. Dann ist der Ausdruck e′ in der Aussage Γ ⊢ e : σ ⇝^{rc} e′, undef das Resultat der Übersetzung. Deshalb ist es nach Entfernung der leeren Instanzensammlung am Ende der zweiten Phase zulässig die Übersetzung kurz als Γ ⊢ e : σ ⇝^{rc} e′ zu notieren. Nun können wir die zwei Hauptsätze für Sprachen mit überladenen Funktionen formalisieren. wohlgetypte überladene Programme können nicht fehlschlagen

Lemma 5.4.1 Γ ⊢ e : σ ⇝^{r} e′ ⟹ e′−̸→^{∗} W rong

wohlgetypte Programme sind determiniert

Lemma 5.4.2

Γ ⊢ e : σ ⇝^{r} e′ ∧ Γ ⊢ e : σ ⇝^{c} e′′ ⟹ (e′⟶^{∗}v ⇔ e′′⟶^{∗}v)

5.5 Erweiterte Typinferenz

Der Typisierungsalgorithmus zum System O ist eine Erweiterung des Algorithmus W von Hindley/Milner. Die Erweiterung besteht darin, daß noch zusätzlich die Erfüllbarkeit der Überladungseinschränkungen berechnet werden muß. Für diese Berechnung wurden die Einschränkungen in die undeterminierten, die inkonsistenten und die determinierten Einschränkungen unterschieden. Die undeterminierten Einschränkungen sind durch ihren Argumenttyp nicht festgelegt und hatten die Form o : α → τ. Die determinierten Einschränkungen sind dagegen durch ihren Argumenttyp bereits für eine Instanzauswahl festgelegt. Die inkonsistenten Einschränkungen sind auch durch ihren Argumenttyp festgelegt, aber es existiert keine Instanz der überladenen Funktion welche Argumente dieses Typs bearbeiten kann.

Die Lösung des Einschränkungsproblems besteht dann darin, entweder inkonsistente Einschränkungen zu finden – dann ist die Unlösbarkeit des Problems festgestellt oder für die determinierten Einschränkungen eine Instanzauswahl durchzuführen und undeterminierte Einschränkungen für die Rechtfertigung dieser Auswahl zu berechnen. Dieses Verfahren wird die Normalisierung des Einschränkungsproblems genannt. Bei der Normalisierung wird eine Menge von möglicherweise determinierten Einschränkungen in eine Menge von undeterminierten Einschränkungen umgewandelt.

5.5.1 Erweiterte Normalisierung

Um einen Typisierungsalgorithmus für das System O_{2} zu entwickeln, ist nur der Normalisierungalgorithmus neu zu definieren, der restliche Typisierungsalgorithmus kann unverändert von System O übernommen werden. Wir folgen dem oben beschriebenen Weg zur Entwicklung der Normalisierung. Für das System O_{2} definieren wir die entsprechenden Begriffe der undeterminierten, inkonsistenten oder determinierten Überladungseinschränkung. Wir benötigen dazu den Kompatibilitätsbegriff für Typkerne.

k ↑ k′ gdw ∀p. ∈ pth(k) ∩ pth(k′).k(p) = k′(p)

Zwei Typkerne sind also kompatibel (kurz: k ↑ k′) wenn sie auf ihrer Überschneidung übereinstimmen. Dieser Begriff wird benötigt, da in dem System O_{2} auf Grund der relevanten Typkerne die Instanzauswahl vorgenommen wird. Wenn also für eine Überladungseinschränkung und eine Überladungsinstanz die entsprechenden relevanten Typkerne der Argumenttypen kompatibel sind, so deutet das auf eine mögliche Instanzauswahl hin. Sei also eine Überladungseinschränkung o : τ → τ′ gegeben, so möchten wir zu einer gegebenen Typothese Γ diejenigen Instanzen kennen, welche möglicherweise ausgewählt werden können. Wir suchen also die Menge der argumentkompatiblen Instanzen.

komp(Γ, o, τ) := {σ_{i} | k <^{r} τ, o : σ_{i} ∈ Γ, k′ <^{i} σ_{i}, k ↑ k′}

Mit dieser Menge können wir nun die Definition der Eigenschaften von Einschränkungen vornehmen. Sei eine Einschränkung o : τ → τ′ und eine Typothese Γ mit Instanzeinträgen gegeben, dann kann die Einschränkung die folgenden Eigenschaften besitzen : undeterminiert |komp(Γ, o, τ)| ≥ 1. Falls es mehrere mögliche Instanzen zur Aus-

wahl gibt, ist die Einschränkung undeterminiert. Falls nur eine Instanz zur Auswahl existiert aber die Forderung der Kernüberdeckung nicht erfüllt ist, dann ist die Einschränkung durch ihren Argumenttyp nicht festgelegt, also undeterminiert.

inkonsistent komp(Γ, o, τ) = ∅

determiniert {σ_{i}} = komp(Γ, o, τ) und für k <^{r} τ, k′ <^{i} σ_{i} gilt k′ <^{k} k (relevante Kernüberdeckung).

Mit den gegebenen Eigenschaften der Einschränkungen können wir nun geradlinig die Normalisierung definieren.

normalize : (Γ, S) → (Γ, S) normalize(Γ, S) =

begin do norm := true; while do norm do begin do norm = false; if ∃o : τ → τ′ ∈ SΓ inkonsistent then error(“T ypisierungsfehler′′); else if ∃o : τ → τ′ ∈ SΓ determiniert

then begin

/ ∗ Man nehme die ausgewählte Instanz ... ∗ /

{σ_{i}} = komp(SΓ, o, τ);

/ ∗... und zerlege den Typ σ_{i} unter Variablenumbenennung. ∗ / structure(σ_{i}) = (C, τ_{1} → τ_{1}′); U = mgu(τ → τ′, τ_{1} → τ_{1}′); S = U ∘ S; Γ = Γ \ {o : τ → τ′} ∪ C; do norm = true;

end end return(Γ, S);

end

Die offene Frage ist nun, terminiert dieser Normalisierungsalgorithmus ? Offensichtlich wird für jede determinierte Einschränkung o : τ → τ′ eine Herleitung S(Γ \ {o : τ → τ′}) ⊢ o : Sτ → τ′ berechnet. Der Normalisierungsschritt ist die Auswahl einer Überladungsinstanz o : σ_{i} um die ∀-Eliminationsregel anwenden zu können. Dabei wird für die Struktur des Instanztyps σ_{i} ≡ ∀\overline{α}.C ⇒ τ_{1} → τ_{1}′ die Existenz eines Unifikators gefordert, also Uτ → τ′ = Uτ_{1} → τ_{1}′. Ein Normalisierungsschritt im Algorithmus entspricht damit einer Regelanwendung in der entsprechenden Herleitung.

(∀E) \frac{(T AUT) Γ.o : σ_{i} ⊢ o : ∀\overline{α}.C ⇒ τ → τ′  Γ ⊢ UC}{Γ.o : σ_{i} ⊢ o : Uτ → τ′}

Der Beweis der Nebenbedingung Γ ⊢ UC ist nach Ausführung des Normalisierungsschrittes allerdings noch offen. Bei der Normalisierung gibt es eine zweigeteilte Strategie um die Überladungseinschränkungen UC herzuleiten. Einerseits werden die determinierten Einschränkungen einem Normalisierungsschritt unterworfen, andererseits werden die undeterminierten Einschränkungen in die Typothese Γ eingefügt. Insgesamt wird also für das Resultat (Γ′, S′) eine normalisierte Herleitung S′Γ′ ⊢ o : S′τ → τ′ aufgebaut d.h. alle Einschränkungen der Typothese S′Γ′ sind undeterminiert. Der Beweisbaum der resultierenden Herleitung für die determinierte Einschränkung ist also sehr klar strukturiert. Die Blätter des Baumes sind immer Anwendungen der (T AUT)-Regel auf Überladungseinschränkungen. Die Verzweigungen sind immer von der oben dargestellten Form von (∀E)-Regelanwendungen. Die linke Prämisse dieser Regelanwendung ist dann immer eine Instanzauswahl (T AUT) Γ.o : σ_{i} ⊢ o : ∀\overline{α}.C ⇒ τ → τ′ und die rechte Prämisse führt für jede Einschränkung aus der Menge C zu einem Zweig des Beweisbaumes. Man beachte, daß bei gegebener Typothese die größte gebundene Einschränkungsmenge C eine obere Schranke für den Verzweigungsgrad des Beweisbaumes setzt. Nun braucht man noch eine Begrenzung für die Höhe des Beweisbaumes. Wir haben jedoch rekursive Überladungspolymorphie ausgeschlossen. Wir definieren einen Abhängigkeitsgraph G_{o}(Γ) zwischen überladenen Funktionen zu einer Typothese Γ durch die Kanten o → o′ gdw ∃o : ∀\overline{α}.C ⇒ τ → τ′ ∈ Γ ∧ o′ : τ_{1} → τ_{1}′ ∈ C. Dann hat dieser Graph offensichtlich keine Zyklen. Also gibt es für jeden Namen o einen Pfad maximaler Länge in dem Graph, diesen Wert nennen wir die Ordnung von o. Nun beschreibt aber diese maximale Länge nach ihrer Definition eben gerade die maximale Höhe eines Beweisbaumes zur Herleitung einer mit o benannten Überladungseinschränkung Γ ⊢ o : τ → τ′. Also terminiert die Normalisierung einer determinierten Einschränkung immer. Nun ordne man jeder Einschränkungsmenge C als Maß eine Sequenz n_{0} … n_{m} ∈ ℕ^{∗} zu, wobei m die maximale Ordnung einer Einschränkung in C ist und n_{i} die Anzahl der Einschränkungen in C angibt welche die Ordnung i besitzen. Bei lexikographischer Ordnung dieses Maßes ist es offensichtlich, daß jeder Normalisierungschritt das Maß der Einschränkungsmenge senkt. Nachdem die lexikographische Ordnung wohlfundiert ist folgt daraus die Terminierung der Normalisierung.

5.5.2 Erkennung leerer Einschränkungen

Eine Einschränkung ist leer, wenn es keine Möglichkeit gibt, diese Einschränkung während der Typisierungsberechnung (bei gegebenen Zustand (S, Γ, τ)) zu determivacous constraints(S, Γ, τ) → (S, Γ, τ) vacous constraints(S, Γ, τ)

/* Definition von Hilfsfunktionen */ res var(o : τ → τ′) = tv(τ′); may relevant(o : τ → τ′) = {α | α rocc τ}; Die Typothese SΓ = T.C wird in die Deklarationen T … … und die Überladungseinschränkungen C aufgeteilt V := tv(S(T, τ));

/* V enthält die Menge der Typvariablen welche möglicherweise während der Typisierung festgelegt werden */

V C := C;

/* V C enthält die Menge der möglicherweise leeren Einschränkungen */ while ∃c ∈ V C.may relevant(c) ⊂ V do

V C := V C \ {c};

/* eine Einschränkung welche möglicherweise determiniert

werden kann ist nicht leer */ V := V ∪ res var(c);

/* die Einschränkung kann ihre Resultatsvariablen determinieren */ od; return(S, Γ \ V C, τ);

Abbildung 5.1: Algorithmus zur Entfernung leerer Überladungseinschränkungen.

nieren. Diese Situation ist offensichtlich der Fall bei einer Einschränkung c = o : α → τ mit der Nebenbedingung α ∉ tv(Γ \ {c}, τ)(quantifizierbare Typvariable), denn die Variablenbedingung zeigt an, daß der Argumenttyp für c nicht festgelegt werden kann. Eine erste Verallgemeinerung dieser Situation ist eine gegebene Einschränkung c = o : τ → τ′ mit α rocc τ, das heißt die besagte Typvariable tritt relevant im Typargument der Einschränkung auf, damit ist eine Determinierung (d.h. eine Festlegung der relevanten Typkerns an dieser Stelle) unmöglich. Wir wollen aber auch den Fall von wechselseitig bezüglichen aber leeren Einschränkungen entdecken (z.B. den Fall Γ = Γ′ ∪ {o : α → β, o : β → α} mit Variablenbedingung tv(Γ′, τ) ∩ {α, β} = ∅). Im Fall der wechselseitig bezüglichen Einschränkungen c_{1}, c_{2} mit α_{1} rocc c_{1}, α_{2} rocc c_{2} wird jeweils die Nebenbedingung für einzelne Typvariablen α_{i} ∉ tv(Γ \ {c_{i}}) verletzt. Um diesen Fall schrittweise bei der algorithmischen Erkennung von leeren Einschränkungen zu behandeln, wird einfach eine Kette von möglichen Determinierungen untersucht. Das heißt Typvariablen werden als determinierbar markiert wenn sie von der Umgebung oder dem Programm festgelegt werden können (also α ∈ tv(Γ, τ)). Die Kette der möglichen Determinierungen wird durch bereits determinierte Einschränkungen erweitert. Die Einschränkungen in einem Zyklus werden dann nie betrachten und bleiben zum Schluß übrig.

Der Algorithmus (sh. Abb. 5.1) bereinigt eine gegebene Typothese, indem die leeren Einschränkungen entfernt werden. Dazu wird die Konstruktion eines Falles versucht um eine Einschränkung während der Typisierungsphase zu determinieren. Zuerst sind alle Einschränkungen determiniert deren relevante Typvariablen in tv(T, τ) zu finden sind (T ist die Menge der Deklarationen eines Programms). Danach wird die Kette der möglichen Determinierungen aufgebaut. Falls also eine Einschränkung o : τ → τ′ durch Betrachtung des Argumenttyps τ als determinierbar behandelt wird, dann können die Typvariablen des Resultatstyps tv(τ′) die Menge der determinierbaren Typvariablen erweitern.

5.5.3 Behandlung von curried überladenen Funktionen

Seien die folgenden Instanzen zu einer überladenen Funktion gegeben

\begin{matrix}o : ∀\overline{α}.C ⇒ T → S → τ_{1} \\ o : ∀\overline{β}.C′ ⇒ T → T → τ_{2} \end{matrix}

Wobei die argumentlosen Typkonstruktoren T und S vordefiniert seien. Die Realisierung der Funktion o stellt zwei Probleme: das der Typisierung und das der Implementierung. Zur Implementierung kann gesagt werden, daß der Code erst nach Verbrauch des zweiten Arguments ausgeführt werden kann. In der Typinferenz soll bereits bei Kenntnis des ersten Argumenttyps die Typisierung durchgeführt werden. Dieses Problem kann durch die Einführung von virtuellen Einschränkungen behandelt werden, so kann die Festlegung des zweiten Argumenttyps verzögert werden. Zu der im Beispiel gegebenen Instanzdeklarationen soll die erweiterte Typinferenz folgende Faktorisierung durchführen. Es soll eine neue Instanzdeklaration in die Typothese eingefügt werden :

o : ∀αβ.{o^{v} : α → β} ⇒ T → α → β

Für jeden der verschiedenen zweiten Argumenttypen wir nun noch eine Instanzdeklaration für die virtuelle Funktion o^{v} in die Typothese eingefügt :

\begin{matrix}o^{v} : ∀\overline{α}.C ⇒ S → τ_{1} \\ o^{v} : ∀\overline{β}.C′ ⇒ T → τ_{2} \end{matrix}

Man bemerke, daß eine weitere Instanz für o mit der Typisierung o : ∀\overline{γ}.C′′ ⇒ T → T′\overline{τ} zu einer Mehrdeutigkeit führen kann. Allerdings wäre eine solche überladene Funktion nicht wohldefiniert. Also kann solch ein Fall bei der Typisierung als Typfehler verworfen werden.

In dem ersten Beispiel haben wir einen Fall behandelt, in dem die Typen des ersten Arguments T übereinstimmten für die verschiedenen Instanzen. Nun wollen wir noch factorize : (S, Γ, o : σ_{i}) → (S, Γ) factorize(S, Γ, o : σ_{i}) =

/* Man nehme den relevanten Typkern von σ_{i} */ k <^{i} σ_{i};

if σ_{i} habe nicht die Struktur o : ∀\overline{α}_{1}.C_{1} ⇒ τ_{1} → τ_{1}′ → τ_{1}′′

then if ∃o : σ′_{i} ∈ SΓ ∧ k′ <^{i} σ′_{i} ∧ k ↑ k′ then error(“Verletzung der Wohldefiniertheit von o”); else return(S, Γ.o : σ_{i});

/* Suche nach Instanz mit Kernübereinstimmung */ else if ∃o : σ′_{i} ∈ SΓ mit k <^{i} σ′_{i}

then begin

σ′_{i} ≡ ∀\overline{α}_{2}.C′ ⇒ τ_{2} → τ_{3} /* Strukturauflösung von σ′_{i} */ if ∃T ∈ T . τ_{3} = T \overline{τ} then error(“Verletzung der Wohldefiniertheit von o”); else if τ_{3} = α → β ∧ C′ = \{o^{v} : k\overline{β} × α → β\}

/* eine weitere Instanz zu einer curried überladenen */ /* Funktion eintragen */ then return(factorize(S, Γ, o^{v} : ∀\overline{α}_{1}.τ_{1} × τ_{1}′ → τ_{1}′′));

else begin

/* o : σ_{i} ist die zweite curried überladene Funktion */ habe τ_{3} die Struktur τ_{2}′ → τ_{2}′′ erzeuge neue Namen o^{v} und \overline{β}

Γ := Γ \{o : σ′_{i}}

∪\{o : ∀α\overline{β}.\{o^{v} : k\overline{β} × α → β\} ⇒ k\overline{β} → α → β\}

∪\{o^{v} : ∀\overline{α}_{2}.C′ ⇒ τ_{2} × τ_{2}′ → τ_{2}′′\};

/* Behandle rekursiv überladene Funktionen mit einer Kette von curried Argumenten */

return(factorize(S, Γ, o^{v} : ∀\overline{α}_{1}.C′ ⇒ τ_{1} × τ_{1}′ → τ_{1}′′)); end end

end

Abbildung 5.2: Behandlung von curried überladenen Funktionen den allgemeinen Fall behandeln in dem die ersten Argumenttypen nur im relevanten Kern übereinstimmen. Seien also die beiden Instanzen der überladenen Funktion o gegeben

\begin{matrix}o : ∀\overline{α}_{1}.C_{1} ⇒ τ_{1} → τ_{1}′ → τ_{1}′′ \\ o : ∀\overline{α}_{2}.C_{2} ⇒ τ_{2} → τ_{2}′ → τ_{2}′′ \end{matrix}

wobei die ersten Argumenttypen im relevanten Kern übereinstimmen sollen, also gelte k <^{r} τ_{1} und k <^{r} τ_{2}. Weiter betrachten wir nun die Kernzerlegungen τ_{1} = k\overline{τ}_{1} und τ_{2} = k\overline{τ}_{2}. Das gemeinsame neue erste Typargument werde nun aus der Kernbelegung mit neuen Typvariablen gebildet τ = k\overline{β}. Wir nehmen weiter einen zweistelligen Typkonstruktor × an welcher in beiden Typargumenten relevant ist, dieser Typkonstruktor soll in Infixschreibweise verwendet werden.

Nun haben wir das Material um die Faktorisierung für den allgemeinen Fall zu behandeln. Es wird wieder ein Instanzeintrag für das gemeinsame erste Argument erzeugt. Man beachte, daß der neue Typkonstruktor × für die Behandlung der Kernzerlegung (also τ = k\overline{β} und τ_{i} = k\overline{τ}_{i}) genutzt wird :

o : ∀αβ.\overline{β}.\{o^{v} : τ × α → β\} ⇒ τ → α → β

Für jede Instanzdeklaration zu o wird eine virtuelle Instanzdeklaration zu o^{v} erzeugt:

\begin{matrix}o_{1}^{v} : ∀\overline{α}_{1}.C_{1} ⇒ τ_{1} × τ_{1}′ → τ_{1}′′ \\ o_{2}^{v} : ∀\overline{α}_{2}.C_{2} ⇒ τ_{2} × τ_{2}′ → τ_{2}′′ \end{matrix}

Wir wollen dieses Verfahren nun als Algorithmus formulieren, um es in der Typisierung einzusetzen. Das ist dann das erste Verfahren welches die Typinferenz für curried überladene Funktionen behandeln kann.

5.5.4 Erweiterter Inferenzalgorithmus

In den vorigen Abschnitten haben wir die Mittel gesammelt um nun den Typisierungsalgorithmus für System O_{2} anzugeben. Ein Programm in System O_{2} besteht aus der Definition der algebraischen Datentypen und einem Programmterm. Zur Typanalyse können wir also eine erweiterte Signatur A = (T , a, D, arg, t) für die algebraischen Datentypen und einen Programmterm p als gegeben ansehen. Zuerst muß nun das Terminationsproblem für Typkonstruktoren gelöst werden, so daß wir eine Striktheitsmarkierung M = (C, r, d) erhalten. Mit der Hilfe der Striktheitsmarkierung ist nun das Kriterium für relevante Typkerne definiert. Die eigentliche Typinferenz entspricht zum großen Teil dem Algorithmus für System O . Die wesentlichen Änderungen finden sich bei der Behandlung der inst-Anweisung und bei der Variablenbindung in der Unifikation. Bei der Bindung [τ/α] einer Typvariablen in der Unifikation wird der neue Normalisierungsalgorithmus aufgerufen. Bei der Behandlung der inst-Anweisung sind zwei wesentliche Änderungen zu betrachten.

Vor der Bindung von Überladungseinschränkungen durch die Generalisierung werden alle leeren Einschränkungen aus der Typothese entfernt. Dieser Schritt kann die Menge der gebundenen Einschränkungen verkleinern und trägt so zu der Effizienz der Typisierung bei. Statt einfach eine neue Instanz o : σ_{i} in die Typothese einzufügen wird die Möglichkeit von curried überladenen Funktionen behandelt.

/* Einfügung einer neuer Überladungsinstanz in die Typothese */ factorize : (S, Γ, o : σ_{i}) → (S, Γ)

/* Entferne leere Einschränkungen aus der Typothese */ vacous constraints : (S, Γ, τ) → (S, Γ, τ)

/* Löse alle determinierten Einschränkungen auf */ normalize : (Γ, S) → (Γ, S)

tp : (S, Γ, p) → (S, Γ, τ)

u, o, λu.e, ee′, let u = e in e′ wie zuvor behandeln

tp(S, Γ, inst o = e in p) =
(S_{1}, Γ_{1}, σ_{i}) = gen(vacous constraints(tp(S, Γ, e)));
(S_{2}, Γ_{2}) = factorize(S_{1}, Γ_{1}, o : σ_{i});
return(tp(p, Γ_{2}, S_{2}));
unify : (τ, τ) → (Γ, S) → (Γ, S)
unify(τ_{1}, τ_{2})(Γ, S) = case (Sτ_{1}, Sτ_{2}) of
Die Fälle (α, α) und (T \overline{τ}_{1}, T \overline{τ}_{2}) wie zuvor behandeln
(α, τ)(τ, α) ⇒ normalize(Γ, [τ/α] ∘ S);

Wir wollen dieses Kapitel mit den Vermutungen der Typisierungseigenschaften beschließen. Zu erwarten wäre, daß die Eigenschaften von System O wie in Kapitel 4 erläutert und bewiesen analog für das System O_{2} gelten. Zur Formulierung des Aussagen wurde in Kapitel 4 der Begriff der eingeschränkten Substitution U geprägt und zur Entwicklung einer Abschätzung auf Typschemata σ ≤_{Γ}^{g} σ′ und Typisierungslösungen (Γ, τ) ≤^{U} (Γ′, τ′) genutzt. Mit Hilfe eines syntaktischen und eines algorithmischen Regelsystems wurden dann die Eigenschaften formalisiert und bewiesen. Es ist zu erwarten, daß sich dieses Vorgehen auch auf System O_{2} erfolgreich fortsetzen läßt. Es sollen nun noch formal die erwarteten Eigenschaften des Algorithmus formalisiert werden.

Vermutung 5.5.1 (Vollständigkeit von System O_{2}) Sei eine Herleitung der Typisierungsaussage SΓ ⊢^{O_{2}} p : σ gegeben, dann terminiert die Berechnung tp(id, Γ, p). Sei das Resultat dieser Berechnung die Typisierungslösung (S′, Γ′, τ′), so gilt für die Typisierungslösung (S′, Γ′′, σ′) = gen(S′, Γ′, τ′) die Abschätzung (S′Γ′′, σ′) ≤^{U} (SΓ, σ) für eine eingeschränkte Substitution U.

Die Korrektheitsaussage ist genauer zu betrachten.

Vermutung 5.5.2 (Korrektheit von System O_{2}) Wenn die Typisierungsberechnung tp(S, Γ, p) mit dem Resultat (S′, Γ′, τ′) terminiert, dann gibt es eine Herleitung für die logische Wohlgetyptheitsaussage S′Γ′ ⊢^{O_{2}} p : τ′

Nun wurde in dem neuen Typisierungsalgorithmus die Routine vacous constraints aufgenommen. Diese Routine entfernt Constraints, wenn durch die Typanalyse erkennbar ist, daß der zum Constraint gehörige Aufruf einer überladenen Funktion niemals terminieren würde. Der Beweis der Korrektheitsaussage konstruiert gewöhnlich aus einer Typisierungberechnung die Herleitung einer logischen Wohlgetyptheitsaussage. Diese Konstruktion bereitet Schwierigkeiten falls im Laufe einer Berechnung Constraints durch die Routine vacous constraints verworfen wurden. In diesem Fall gäbe es in der Berechnung keine Entsprechung zu der Herleitung des verworfenen Constraints. Es ist zu erwarten, daß die nichtterminierenden Aufrufe von überladenen Funktionen in manchen Fällen mit unendlichen logischen Herleitungen korrespondieren. Ein Beweis der Korrektheit des Typisierungsalgorithmus (mit der Routine vacous constraints) sollte Licht in diese Situation bringen.

146 KAPITEL 5. ERWEITERUNG DES ÜBERLADUNGSSYSTEMS

Schluß

6.1 Zusammenfassung

Ausgangspunkt der vorliegenden Arbeit ist die Überzeugung, daß getyptes Programmieren die Fehlerbehaftetheit von Programmen senken kann ohne den Programmierer in den Ausdruckmöglichkeiten einzuschränken. Das Ziel der vorliegenden Arbeit ist es eben die Ausdrucksmöglichkeiten des getypten Programmierens auszuweiten. Fortschritte in dieser Aufgabe können an zwei Aspekten ermessen werden. Zum einen sollen die Ausdrucksmöglichkeiten der Programmiersprache erweitert werden zum anderen soll der Benutzer dieser Programmiersprache nicht mit der Deklaration komplexer Typangaben belastet werden. Kurz, die neue Sprache soll ausdrucksmächtig aber einfach benutzbar sein. Eine Programmiersprache gewinnt dann an Ausdruckskraft, wenn sich mit kürzeren Programmtexten die gleichen Algorithmen formulieren lassen oder wenn sich Algorithmen allgemeiner formulieren lassen, so daß sie mit verschiedenen Argumenten arbeiten können. Die Verallgemeinerung von Algorithmen führt auch zu kürzeren Programmen da weniger Versionen eines ähnlichen Algorithmus codiert werden müssen. Der Ansatzpunkt der vorliegenden Arbeit ist die Nutzung von Polymorphie und Typinferenz. Die Polymorphie ermöglicht es Programme so zu schreiben, daß die Programmteile (z.B. Funktionen) anstatt bei der Definition festgelegt, bei der Benutzung den Anforderungen der Programmumgebung (z.B. den aktuellen Argumenten) angepaßt werden. Die Typinferenz nimmt dabei dem Programmierer die Bürde ab, sich um die Einführung der Parameter bei der Definitionsstelle und die Besetzung der Parameter bei der Benutzung zu kümmern. Das Neuartige der vorliegenden Arbeit ist es, daß zum ersten Mal die vollständige Typinferenz für die Verbindung von parametrischer und Überladungspolymorphie gelungen ist. Genaugenommen war Typinferenz für parametrische und Überladungspolymorphie mit Einschränkungen bereits realisiert und in der vorliegenden Arbeit ist es gelungen, diese Einschränkungen aufzuheben.

Die Basis des vorgestellten Ansatzes ist das Hindley/Milner System zur Behandlung der parametrischen Polymorphie. Viele Ideen zur Behandlung von Überladungspolymorphie sind dem Typklassenkonzept aus der Sprache Haskell entnommen, jedoch unterscheidet sich unser Ansatz in zwei wesentlichen Punkten von den Typklassen. Zum einen kann die Überladung im Typklassenansatz nur mit der Definition einer allgemeinsten Typklasse behandelt werden, so daß jede Überladungsinstanz durch die Instantiierung des Klassentyps getypt werden muß. Die Einschränkung der notwendigen Existenz eines allgemeinsten Überladungstyps wurde in unserem System aufgehoben wodurch die Ausdrucksmöglichkeiten für die Überladungsinstanzen erweitert wurden. Der zweite Unterschied zwischen Typklassen und unserem Ansatz ist, daß unser Ansatz nur Funktionstypen für die Instanzen zuläßt. Diese Entscheidung ist einerseits eine Einschränkung gegenüber den Typklassen andererseits resultiert daraus die Aufhebung des Mehrdeutigkeitsproblems für Überladung. Wegen der Aufhebung des Mehrdeutigkeitsproblems konnte erstmals eine kompositionale Semantik für Überladung und eine volständige Typinferenz für Überladung angegeben werden. Ein weiterer Fortschritt in der Benutzbarkeit ist die Aufhebung der syntaktischen Restriktionen für die Typen der Überladungsinstanzen. Damit können Typfehlermeldungen semantisch begründet werden und bleiben nicht wie bisher Entwurfsentscheidungen des Typisierungsalgorithmus.

Die wesentlichen Resultate der Arbeit lassen sich in drei Gruppen aufteilen. Zur ersten Gruppe gehört die Entwicklung eines Ansatzes zur Behandlung von Überladung und parametrischer Polymorphie welcher die Probleme der Typklassen aufhebt. Die Resultate der ersten Gruppe sind Ideen von Martin Odersky und Philip Wadler und wurden in der gemeinschaftliche Arbeit [OWW95] vorgestellt. Das Resultat ist in dem logischen System O präsentiert. Der Rest der Arbeit beschäftigt sich mit der algorithmischen Realisierung un der Verallgemeinerung des Systems. Damit konnten die syntaktischen Restriktionen für die Typen der Überladungsinstanzen aufgehoben werden. Dieser zweite Teil ist meine eigene Entwicklung. Tabellarisch lassen sich die Resultate wie folgt zusammenfassen :

Der Ansatz logisches System O.

• Aufhebung der Klassendefinitionen ⟹ größere Ausdrucksmöglichkeiten für Überladungsinstanzen.

• Festlegung auf Instanzfunktionen ⟹ Aufhebung des Mehrdeutigkeitsproblems für Überladung. ⟹ erste kompositionale Semantik für die Verbindung von Überladung und parametrischer Polymorphie.

Die Typinferenz algorithmisches System O.

• Normalisierung der Überladungseinschränkungen mit Beweis der Terminierung bei allgemeinster Lösung.

• Beweis der Vollständigkeit des algorithmischen Systems.

⟹ prinzipielle Typeigenschaft für eine System mit Überladung und parametrischer Polymorphie.

Aufhebung der syntaktischen Einschränkungen System O_{2}

• Ausdehnung der Parametrizität auf algebraische Datentypen.

– Charakterisierung der algebraischen Datenwerte durch eindeutige Zerlegung

– Charakterisierung der Funktionen zwischen algebraischen Datentypen durch Schemenrepräsentation.

– Aufstellung des Terminationsproblems für Typkonstruktoren. ⟹ neue Programmanalysen zur Entdeckung von Divergenzen in Programmen.

∗ Divergenz für algebraische Datentypen.

∗ partielle Divergenz für Funktionen zwischen algebraischen Datentypen.

∗ Entdeckung leerer Überladungseinschränkungen.

• ⟹ Entwicklung der Überladungspolymorphie auf Basis von relevanten Typkernen

– Semantische Begründung von Typfehlern (Wohldefiniertheit der überladenen Funktion).

– Operationale Semantik für Instanzauswahl zur Laufzeit.

– Übersetzung mit vollständiger Auflösung der Instanzauswahl.

– Erweiterung des algorithmischen Systems

• ⟹ Erste Methode zur Behandlung von überladenen Funktionen mit schrittweisem Argumentverbrauch (curried Funktionen).

Im folgenden weisen die Pfeile ⟹ auf Ergebnisse auf Lösungen von bisher ungelösten Problemen hin.

6.2 Ausblick

Die Ergebnisse der vorliegenden Arbeit können in vier Richtungen ausgebaut werden.

Verallgemeinerung Bei der Analyse unseres Ansatzes zeigt sich, daß die Hindley/Milner Methodik um Constraint-Lösung erweitert wurde. Da die meisten Typsysteme als Erweiterungen des Hindley/Milner Systems zu identifizieren sind stellt sich die Frage, ob diese Beobachtung zu einem allgemeinen Rahmen für Typsysteme formalisiert werden kann. Durch eine axiomatische Fassung dieses Vorgehens wurde in Zusammenarbeit mit Martin Odersky und Martin Sulzmann [SOW96] ein genereller Rahmen für die Einbettung von neuen Ausdruckmitteln in die Typinferenz geschaffen. Dieser allgemeine Rahmen heißt Typsysteme mit Constraints. Der Kern des Systems ist das Hindley/Milner System und der offene Parameter ist ein Constraintsystem. Es wurden die klassischen Eigenschaften des Typisierungsalgorithmus bewiesen (Vollständigkeit, Korrektheit, prinzipielle Typeigenschaft) und die Anwendbarkeit des Ansatzes auf verschiedene Bespiele vorgeführt. Als Anwendung wurden Constraintsysteme zur Behandlung von erweiterbaren Records, Typklassen, Überladung und Subtypen beschrieben. Aktuell wird gerade eine Formalisierung des Normalisierungsbegriffes mit Hilfe der auf kategorischer Logik basierenden Arbeiten von Seely et. al. [MPSS95] untersucht. Das System O und System O_{2} würde als Beispiel dienen, um die Konsistenz der Axiome nachzuweisen.

Zusammenhang der Polymorphiearten In der Arbeit [BTCGS91] wurde durch eine Übersetzung der Zusammenhang zwischen Subtyppolymorphie und parametrischer Polymorphie gezeigt. Diese Übersetzung (genannt Penn-Überset-zung nach der Autorengruppe in der Universität von Pennsilvania) reduzierte getypte Terme des System F_{≤} auf Terme des System F. Dabei ist das System F_{≤} mit F-gebundener Polymorphie eine Anreicherung des System F. Also zeigt die Übersetzung, daß die neuen Sprachmittel von System F_{≤} bereits in System F realisiert werden können. Eine ähnliche Reduzierung der System O_{2} Terme zu Termen des System F wurde in der vorliegenden Arbeit als Übersetzung ⇝^{c} mit Instanzauswahl vorgestellt. Eine weitere Untersuchung über Einbettung von Records in die Systeme F_{≤} und O zeigte, daß die Penn-Übersetzung auch für diesen Fall erweitert werden kann. Für System O ist sogar eine Reduktion der Records auf algebraische Datentypen möglich. Ein Beweis dieser Zusammenhänge würde zu Einsichten in die Kernelemente der Objektorientierung führen. Die Resultate könnten zu Kalkülen für die Modellierung von objektorientierten Sprachmitteln führen.

Implementierung Um die praktische Relevanz der Resultate dieser Arbeit nachzuweisen, wäre eine Implementierung interessant. Zum einen wäre damit ein praktischer Test des Typisierungsaufwandes möglich. Zum anderen wäre es interessant zu untersuchen, welche Algorithmen sich durch die neuen Sprachmittel besonders effizient formulieren lassen. Eine funktionale Sprache mit Zustandsmonaden, algebraischen Datentypen und Records wurde bereits realisiert, so daß sich die neuen Sprachmittel für Überladung darin einbetten liesen.

abstrakte Semantik Ziel eines semantischen Modells ist es die Widerspruchsfreiheit des logischen Systems zu zeigen und neue Eigenschaften der Sprache zu entdecken. Die Eigenschaften sind meist als Programmäquivalenzen formuliert, so daß sich daraus Programmanalysen und beweisbar korrekte Programmtransformationen ergeben können. In der vorliegenden Arbeit wurde dieses Vorgehen mit der Anwendung der Parametrizität auf algebraische Datentypen und Überladung vorgeführt. Als Resultat erhielten wir Programmanalysen zur Erkennung von Divergenzen und eine Programmtransformationen welche, auf die Auswahl von leeren Überladungseinschränkungen verzichtet.

Aus diesem Grund wäre es interessant eine Semantik mit partiellen Äquivalenzrelationen für System O zu entwickeln. Daraus ergäbe sich eine Formulierung der relationalen Parametrizität für Überladung.

Aktuelle Entwicklungen auf dem Gebiet der semantischen Modellierung haben zu spieltheoretischen Modellierungen geführt und damit zur Lösung des vollen Abstraktheitsproblems für PCF (das Kernproblem der Programmsemantik in den letzten 20 Jahren). Ein voll abstraktes Modell für Überladung mit Hilfe eines spieltheoretischen Modells könnte zu verfeinerten Programmanalysen und Programmtransformationen führen.

152 KAPITEL 6. SCHLUSS

Literaturverzeichnis

[AC93] R. M. Amadio and L. Cardelli. Subtyping recursive types. TOPLAS Tarnsactions on Programming Laguage Systems, 15(4):575–631, September 1993.

[ACPP91] Martín Abadi, Luca Cardelli, Benjamin Pierce, and Gordon Plotkin. Dynamic typing in a statically typed language. ACM Transactions on Programming Languages and Systems, 13(2):237–268, April 1991.

[Aug93] Lennart Augustsson. Implementing Haskell overloading. In Functional Programming and Computer Architecture, pages 65–73, June 1993.

[Bar92] H.P. Barendregt. Handbook of Logic in Computer Science, volume 2, chapter Lambda Calculi with Types, pages 118–310. Oxford Science Publications, May 1992.

[BFSS90] E.S. Bainbridge, P.J. Freyd, A. Scedrov, and P.J. Scott. Functorial polymorphism. Theoretical Computer Science, 70:35–64, 1990.

[BTCGS91] V. Breazu-Tannen, T. Conquand, C. A. Gunter, and A. Scedrov. Inheritance as implicit coercion. Information and Computation, (93):172–221, 1991.

[CGL93] Giuseppe Castagna, Giorgio Ghelli, and Giuseppe Longo. A semantics for λ&−early: A calculus with overloading and early binding. In M. Bezem and J.F. Groote, editors, Typed Lambda Calculi and Applications, International Conference on Typed Lambda Calculi and Applications, TLCA ’93, March 1993, Utrecht, The Netherlands, Proceedings, pages 107–123, New York, March 1993. Springer-Verlag. Lecture Notes in Computer Science 664.

[Che94] Kung Chen. A Parametric Extension of Haskell’s Type Classes. PhD thesis, Yale University, New Haven, Connecticut, December 1994. YALEU/DCS/RR-1057.

[CHO92] Kung Chen, Paul Hudak, and Martin Odersky. Parametric type classes. In Proc. of Lisp and F.P., pages 170–181. ACM, 1992.

[CO92] Kung Chen and Martin Odersky. Type inference for parametric type classes. Research Report YALEU/DCS/RR-900, Yale University Department of Computer Science, New Haven, Connecticut, June 1992.

[COH91] Kung Chen, Martin Odersky, and Paul Hudak. Type inference for parametric type classes. Technical Report YALEU/DCS/RR-90, Yale University, June 1991.

[DCO96] Dominic Duggan, Gordon Cormack, and John Ophel. Kinded type inference for parametric overloading. Acta Informatica, (33):21–68, 1996.

[DM82] L. Damas and R. Milner. Principal type-schemes for functional programs. In POPL’ 82, pages 207–211. ACM, 1982.

[DM86] Gordon Plotkin David MacQueen. An ideal model for recursive polymorphic types. Information and Computation, 71:95–130, 1986.

[DO94] Dominic Duggan and John Ophel. Kinded parametric overloading. Technical Report CS-94-35, University of Waterloo, September 1994.

[Fre90] Peter Freyd. Algebraically complete categories. In A. Carboni et. al., editor, Como Category Theory Conference, pages 95–104. Springer Verlag, 1990. Lec. Notes in Math. 1488.

[Fre92] Peter Freyd. Remarks on algebraically compact categories. In M. Fourman et. al., editor, Applications of Categories in Computer Science, pages 95–106. Cambridge University Press, 1992. Lecture Note Series 177.

[Fre93] P. Freyd. Structural polymorphism. Theoretical Computer Science, 115:107–129, 1993.

[Gir72] J.-Y. Girard. Interpretation fonctionelle et elimination des coupures d’odre superieur. PhD thesis, Universite Paris VII, 1972.

[Gun94] Carl A. Gunter. Handbook of Logic in Computer Science, volume 4, chapter The semantics of types in programming languages, pages 395– 476. Claredon Press Oxford, April 1994.

[Hen93] Fritz Henglein. Type inference with polymorphic recursion. TOPLAS, 15(2):253–286, April 1993.

[HHJW96] Cordelia V. Hall, Kevin Hammond, Simon L. Peyton Jones, and Philip L. Wadler. Type classes in Haskell. TOPLAS, 18(2):109–138, March [HHPW94] Cordelia Hall, Kevin Hammond, Simon Peyton Jones, and Philip Wad-

ler. Type classes in Haskell. pages 241–256, 1994. Springer LNCS 788.

[JJ96] Johan Jeuring and Patrik Janson. Polytypic programming. In J. Launchbury, Erik Meijer, and T. Sheard, editors, Advances in Functional Programming, pages 68–111, Olympia, WA, USA, 1996. Springer Verlag. LNCS 1129.

[Jon92] Mark Philip Jones. Qualified Types: Theory and Practice. PhD thesis, Oxford University, July 1992.

[Jon93] Mark P. Jones. A system of constructor classes: overloading and implicit higher-order polymorphism. In Proc. of FPCA ’93, pages 52–61. ACM, June 1993.

[JP93] Mark Jones John Peterson. Implementing type classes. In ACM-SIGPLAN-PLDI ’93. ACM, 1993.

[Kae88] Stefan Kaes. Parametric overloading in polymophic programming languages. In H. Ganzinger, editor, Proc. of the European Symposium on Programming, pages 133 – 144. Springer Verlag, 1988.

[Kae92] Stefan Kaes. Type inference in the presence of overloading, subtyping and recursive types. Lisp and F.P., pages 193–204, June 1992.

[Lan72] Saunders Mac Lane. Kategorien. Springer Verlag, 1972.

[LM91] Xavier Leroy and Michel Mauny. Dynamics in ML. In John Hughes, editor, Proceedings Functional Programming Languages and Computer Architecture, 5th ACM Conference, Cambridge, MA, USA, pages 406– 426. Springer-Verlag, August 1991. Lecture Notes in Computer Science 523.

[LMM87] J-L. Lassez, M.J. Maher, and K. Marriott. Unification revisited. Foundations of Deductive Databases and Logic Programming, pages 587 – 625, 1987.

[Lon95] G. Longo. Parametric and type-dependent polymorphism. Fundamenta Informaticae, (22):69–92, 1995.

[Mai91] Harry G. Mairson. Outline of a proof theory of parametricity. In J. Hughes, editor, Functional Programming Languages and Computer Architechture, pages 311–327, LNCS 523, August 1991. ACM, Springer Verlag.

[MFP91] Erik Meijer, Maarten Fokkinga, and Ross Paterson. Functional programming with bananas, lenses, envelopes, and barbed wire. In John Hughes, editor, Proceedings Functional Programming Languages and Computer Architecture, 5th ACM Conference, Cambridge, MA, USA, pages 124–144. ACM, Lecture Notes in Computer Science 523, August 1991.

[MH95] Erik Meijer and Graham Hutton. Bananas in space: Extending fold and unfold to exponential types. In FPCA ’95, pages 324–333, La Jolla, California, June 1995. ACM.

[Mil78] Robin Milner. A theory of type polymorphism in programming. Journal of Computer and System Sciences, 17:348–375, Dec 1978.

[MPSS95] Max P. Mendler, Prakash Panangaden, P. J. Scott, and R. A. G. Seely. A logical view of concurrent constraint programming. Nordic Journal of Computing, 2:182–221, 1995.

[MR91] QingMing Ma and John C. Reynolds. Types, abstraction and parametric polymorphism, part 2. In 7^{th} Conf. on Mathematical Foundations of Programming Semantics, pages 1–40, LNCS 598, 1991. Springer Verlag.

[NP93a] Tobias Nipkow and Christian Prehofer. Type checking type classes. 20^{th} POPL, pages 409–418, 1993.

[NP93b] Tobias Nipkow and Christian Prehofer. Type reconstruction for type classes. Journal of Functional Programming, 1(1):1–24, January 1993. Cambridge University Press.

[NS91] Tobias Nipkow and Gregor Snelting. Type classes and overloading resolution via oder-sorted unifikation. FPCA 91, pages 1–14, August 1991. Springer LNCS 523.

[OWW95] Martin Odersky, Philip Wadler, and Martin Wehr. A second look at overloading. In Proc. ACM Conf. on Functional Programming and Computer Architecture, pages 135–1469, June 1995.

[PA93] Gordon Plotkin and Martin Abadi. A logic for parametric polymorphism. In Typed Lambda Calculi and Applications TLCA ‘93, pages 361 – 375, LNCS 664, March 1993. Springer Verlag.

[Rey74] J.C. Reynolds. Towards a theory of type structure. In Ehrig et. al., editor, Mathematical Foundations of Software Development, pages 408 – 425. Springer Verlag, 1974.

[Rey83] John C. Reynolds. Types, abstraction and parametric polymorphism. In R. E. A. Mason, editor, Information Processing 83, pages 513–523. Elsevier Science (North Holland), 1983.

[RH95] Greg Morisett Robert Harper. Compiling polymorphism using intensional type analysis. In POPL ’95, pages 130–141. ACM, 1995.

[Rob65] J.A. Robinson. A machine-oriented logic based on the resolution principle. JACM, 12(1):23–41, 1965.

[Rou90] François Rouaix. Safe run-time overloading. In 17^{th} POPL, pages 355– 366. ACM, January 1990.

[RR94] E.P. Robinson and G. Rosolini. Reflexive graphs and parametric polymorphism. In 9^{th} Symposium on Logic in Computer Science, pages 364–371. IEEE, IEEE Press, July 1994.

[Smi91] Geoffrey S. Smith. Polymorphic type inference for languages with overloading and subtyping. PhD thesis, Cornell University, Ithaca, NY, August 1991.

[SOW96] Martin Sulzmann, Martin Odersky, and Martin Wehr. Type inference with constrained types. Technical Report 28, Universität Karlsruhe, July 1996. submited to POPL’97.

[Str67] Christopher Strachey. Fundamental concepts in programming languages. In unpublished, editor, International Summer School in Programming Languages, Copenhagen, August 1967.

[Tsu92] Hideki Tsuiki. A Record Calculus with a Merge Operator. PhD thesis, Keio University, 1992.

[Tsu94] Hideki Tsuiki. On typed calculi with a merge operator. In 14th Conference on Foundation of Software Technology and Theoretical Computer Science, pages 101–112. Springer Verlag, 1994. LNCS 880.

[Tsu95] Hideki Tsuiki. A denotational model of overloading. Technical Report KSU/ICS-95-01, Kyoto Sangyo University, June 1995.

[Vol93] Dennis Volpano. A critique of type systems for global overloading. Computer Science Technical Report NPSCS-94-006, Naval Postgraduate School, October 1993.

[Wad93] Philip Wadler. Theorems for free! In Proc. of FPCA ’89, pages 347–359. ACM, 1993.

[WB89] Philip Wadler and Stephen Blott. How to make ad-hoc polymorphism less ad-hoc. In POPL ’89, pages 60–75. ACM, January 1989.

[WO96] M. Wehr and M. Odersky. Proof of the principal type property for system O. Technical report, Universität Karlsruhe, Interner Bericht 16/96, June 1996.