• Keine Ergebnisse gefunden

Die vollst¨andigen Namen f¨ur die algebraischen Sprachen sind anders als die einfachen Typterme aus Abschnitt 2.1.2 wie folgt aufgebaut:

name::== inst: type

inst::== ide[name, . . . ,name]

var type::== type

inst: type

- Namensinstanz und Typ - instanziierter Bezeichner - Variable

- Funktionstyp

Namen bestehen also aus zwei Teilen, ihrer Namensinstanz und ihrem Typ, und sind vor allem keine Variablen. Variablen stehen nur f¨ur Namensinstan-zen inst, das sind einfache (mit Herkunft annotierte) Bezeichner ide mit einer je nach Parametrisierung passenden Instanzliste von (vollst¨andigen) Namen.

Die Namensterme sindfrei generiert und initial. (DieGrammatiken hier ent-sprechen den Datentypen ausstrikten Sprachen wieOpal,pvsundml, aber nicht Haskell.) Die ersten Namensinstanzen inst sind daher unparametri-siert mit leeren Instanzlisten und erst damit kann man echt instanziierte Namen bilden. Dar¨uberhinaus gibt es keine zyklischen Namen, beispielswei-se kann sich derpartiell notierte Name <[nat, <] nicht selbst enthalten, weil der zugeh¨orige vollst¨andige Name unendlich w¨are:<[nat, <[nat, <[. . .]]]. Der hierarchische und zyklusfreie Aufbau der Namen wird in Kapitel 8 ausge-nutzt, um Deklarationen schrittweise und inkrementell, aber unabh¨angig von ihrer textuellen Position zu analysieren.

Namen sind entweder Typen oder Funktionen (mit ihrem Typ). Insbeson-dere die zweistelligen Typkonstruktoren → und × kann man sich als gene-rische Typbezeichner aus einer mit zwei Typen parametrisierten Struktur

vorstellen, wobei von einer systematischen Pr¨afix-Notation (wie ×[α, β]) aus Lesbarkeitsgr¨unden abgewichen wird.

Genau genommen ist f¨ur Funktionen die k¨urzere Repr¨asentationinst: inst an Stelle von inst: inst:type ausreichend. Wenn man das Schl¨usselwort typeals spezielle Namensinstanz betrachtet, dann w¨are sogar insgesamt eine Namensmodellierung name ::== inst: inst m¨oglich, die allerdings einen unsinnigen Namen, der mit type beginnt, nicht ausschließen w¨urde.

F¨ur eine noch k¨urzere Notationskonvention kann auf die explizite Typanno-tation mittypeganz verzichtet werden; Typnamen w¨aren dann an fehlenden Typannotationen erkennbar. Die Modellierung als Grammatik s¨ahe dann wie folgt aus:

name::== inst

inst: inst inst::== . . .

- Typname - Funktionsname - wie oben

Wenn man allerdings sowohl vollst¨andige als auch partielle Namen (aus Ab-schnitt 5.4) zusammen betrachtet, dann kann man einen vollst¨andigen Typ-namen nicht von einem partiellen Namen ohne Typannotation unterscheiden.

5.3.1 Substitution

Substitutionen sind endliche Abbildungen von nummerierten Variablen auf die Namensinstanzen inst. (Statt var(n) wird α, β, . . . geschrieben.) Die Unifikation zweier vollst¨andiger Namen, einer mit formalen und der ande-re mit aktuellen Parametern, liefert bei einer korande-rekten Instanziierung eine Substitution, die angewendet auf den formalen Namen exakt den Ersetzungs-prozess von vollst¨andigen formalen Parametern durch passende vollst¨andige aktuelle Parameter widerspiegelt:

set[α: type, β:rel[α]]

set[nat: type, <0Nat:rel[nat]]

- formal - aktuell

Statt aber ganze Teilb¨aume, etwaβ:rel[α] durch<0Nat: rel[nat], zu erset-zen, werden nur Variablen, also einfache Bl¨atter substituiert. Beim sequen-ziellen Ersetzen ganzer Teilb¨aume m¨usste die Reihenfolge beachtet werden:

am einfachsten w¨are es, erst β:rel[α] durch <0Nat: rel[nat] und anschlie-ßend α: typedurch nat: typezu ersetzen; w¨urde dagegen zuerstα: type durch nat: type ersetzt, dann m¨usste auch der Typ des zweiten formalen

Parameters vonrel[α: type] zurel[nat: type] ge¨andert und anschließend der ver¨anderte Teilbaumβ: rel[nat] durch<0Nat: rel[nat] ersetzt werden.

Der parallele Ersetzungsprozess von ganzen Teilb¨aumen ist also viel kompli-zierter als die bekannte (parallele oder sequenzielle) Substitution von atoma-ren Variablen. Gew¨ohnungsbed¨urftig ist lediglich, dass man einer Variablen nicht direkt ansieht, ob sie f¨ur einen Typ oder eine Funktion steht. Diese Rolle ergibt sich allein aus ihrer Position im vollst¨andigen Namensterm. Variablen stehen dabei immer typkonform f¨ur Namensinstanzen.

5.3.2 Unifikation

Die Substitutionen f¨ur die Variablen ergeben sich durch Unifikation der voll-st¨andigen formalen und aktuellen Namen mit Typ. F¨ur den Typparameter α wird damit z.B. gew¨ahrleistet, dass der aktuelle Name nat tats¨achlich ein Typ (und keine Funktion) ist. Die Unifikation des vollst¨andigen Namens

<0Nat: rel[nat] mit dem vollst¨andigen formalen Parameter<:rel[α] liefert nicht nur eine Substitution f¨ur die Variable <, sondern – ¨uber den Typ – auch f¨ur die Variable α und garantiert so die Konsistenz (und sp¨ater eine Uberlagerungsaufl¨¨ osung) f¨ur den Typparameter. Bei einer Abarbeitung der Parameter in beliebiger Reihenfolge werden die Substitutionen entsprechend komponiert.

Beim Namen {} f¨ur die leere Menge aus der parametrisierten Struktur Set werden die Variablen wie bei polymorphen Funktionen gebunden. Eine fast vollst¨andige Notation, bei der die Benennung der gebunden Variablen irrele-vant ist (β statt <), w¨are folgende:

∀α β.{}0Set[α: type, β: rel[α]] : set0Set[α: type, β: rel[α]]

Zum Zwecke der Aufl¨osung der Instanz Foo[nat, <,{}] wird der generische Name {} mit frischen Unbekannten instanziiert: {}[γ, δ] : set[γ, δ]. Dieser Namenskandidat wird nun mit dem formalen Parameter s: set[α, <] der Struktur Foo unifiziert. Die Unifikation beider set-Typen liefert eine Sub-stitution [α := γ, <:= δ], was zusammen mit [α := nat, <:= <0Nat] durch die ersten beiden Parameter die konkrete Typinstanz set[nat, <0Nat] liefert und damit die Namensinstanz{}[nat, <0Nat]. F¨ur dengenerischimportierten Namen {}aus der Struktur Setergibt sich also per Unifikation die konkrete Instanz.

Gem¨aß dem Annotationskonzept von Opal besteht ein Name aus vier

Tei-len: seinem Bezeichner, seiner Herkunft, seiner Instanz und seinem Typ. Ein Name ist vollst¨andig bekannt, wenn alle Teile vollst¨andig bekannt sind. Bei einempartiellen Namen sind die Herkunft, die Instanz und der Typoptionale Annotationskomponenten; nur der einfache Bezeichner (ganz links vorne) ist obligatorisch. Diese Zerlegung in vier Teile f¨uhrte in [Reu98] dazu, dass statt einer drei Variablen betrachtet wurden: getrennt (und typverschieden) f¨ur Bezeichner, Herkunft und Instanz. Dass keine Variable f¨ur den Typ n¨otig ist, wurde dabei korrekt erkannt. Weniger umst¨andlich ist die hier angegebene Zerlegung vollst¨andiger Namen in zwei Teile: inNamensinstanz und Typ.