• Keine Ergebnisse gefunden

Ein Motiv f¨ur selektive Importe ist, den Namensraum m¨oglichst klein und uberschaubar zu halten. Durch vollst¨¨ andige Importe, f¨ur die es in pvs kei-ne Alternativen gibt, wird manchmal zu viel importiert. Statt aber wie in Opal die erw¨unschten Namen aufzulisten, wird zun¨achst in Abschnitt 7.2.1 vorgeschlagen, unerw¨unschte Namen auszuschließen.

Beim selektiven Import mit dem Bezeichneridenachonlywerden alle¨ uber-lagerten Namen importiert. Wieviele bzw. welche der ¨uberlagerten Namen importiert werden, kann zwar vom Compiler genau gemeldet werden, ist aber besonders bei Reexporten f¨ur den Benutzer nicht sehr transparent. Um aus-gew¨ahlte ¨uberlagerte Namen auch einzeln importieren zu k¨onnen, darf der Bezeichner ide annotiert werden. Konkret kann in Opal nach only eine Liste partieller Namen angegeben werden.

Um Namensidentifizierungen zu erleichtern, wird in Abschnitt 7.2.2 auf einen vorteilhaften getrennten Import von Typen und Funktionen verwiesen. Aus generischen Importen k¨onnen Namen direkt nur generisch importiert werden.

Um illegale Instanziierungen durch Instanzannotationen auszuschließen, wird in Abschnitt 7.2.3 eine spezielle generische Instanz aus Platzhaltern f¨ur for-male Parameter konzipiert. Diese Platzhalter erm¨oglichen vor allem exakte Typannotationen.

F¨urdirekte Importe (Abschnitt 7.3) ergeben sich wesentliche Erleichterungen zur Festlegung von only-Namen. Beim Reexport werden Herkunfts- und Instanzannotationen f¨ur zu importierende Namen ber¨ucksichtigt. S¨amtliche Probleme f¨ur transitive Importe enth¨alt Abschnitt 7.4.

7.2.1 Selektiver Ausschluss

Ein spezieller Grund f¨ur selektive Importe kann darin liegen, unerw¨unschte Uberlagerungen¨ zu vermeiden, um sich z.B. Herkunftsannotationen f¨ur typ-gleiche Funktionen zu ersparen. Beim Import aus zwei Strukturen w¨urde ein uberlagerter Bezeichner dazu in einer¨ only-Liste einfach nicht aufgef¨uhrt.

Die explizite Auflistung aller anderen (n¨otigen oder nicht st¨orenden) Bezeich-ner k¨onnte allerdings m¨uhsam sein. Komplement¨ar zu den only-Importen w¨aren daher zus¨atzliche allbut-Importe sinnvoll:

import Natallbut + import Real only +. . .

Ein Problem beim Ausschluss von Namen ist es, wenn derselbe Name an mehreren Stellen importiert wird. Vollst¨andige und insbesondere transitive Importe k¨onnten einen sorgf¨altigen Namensausschluss wieder zunichte ma-chen. Vollst¨andige und selektiveallbut- und auchonly Importe derselben Instanz einer Struktur machen zusammen also nicht viel Sinn. F¨ur Namen, die durch allbut explizit nicht importiert werden sollen, will man zumin-dest wissen, ob sie nicht doch durch andere Importe hinzukommen. Importe sollten sich also nicht widersprechen.

Bei direkten Importen (Abschnitt 7.3) k¨onnen Kollisionen schon syntaktisch vermieden werden, indem man pro Instanz einer Struktur entweder

• einen completely- oder

• einen allbut-Import oder

• nur only-Importe erlaubt.

Davon unber¨uhrt kann die M¨oglichkeit bleiben, dieselben Importe zu wieder-holen.

Der Ausschluss spezieller Instanzen w¨urde die Repr¨asentation der Namens-r¨aume erschweren:

import Seqallbut seq[bool] - illegal

Da aber auch der entsprechende only-Import problematisch ist, sollte man eine Instanzannotation f¨ur den importierten Bezeichner gar nicht vorsehen (Abschnitte 7.2.3 und 7.4.2).

Ein Nachteil von allbut-Importen ist, dass die verwendbaren Bezeichner der importierten Namen nicht offensichtlich sind. Das gilt auch f¨ur vollst¨ an-dige Importe aber versch¨arft f¨urallbut, weilnicht-verwendbare Bezeichner explizit aufgef¨uhrt werden k¨onnen. F¨ur uberlagerte¨ Bezeichner ist aber ein selektiver Ausschluss ideal, ansonsten sind only-Importe vorzuziehen.

7.2.2 Trennung von Typen und Funktionen

Die Gleichberechtigung von Typen und Funktionen ist bez¨uglich der Para-metrisierung und Instanziierung beabsichtigt; der Benutzer muss allerdings Typen und Funktionen gut unterscheiden k¨onnen. Funktionen werden – mo-mentan – haupts¨achlich in Ausdr¨ucken und – im Vergleich zu Typen seltener – in Instanzen appliziert. Beim Import eines unannotierten Bezeichners ide ist diese Unterscheidung syntaktisch nicht so offensichtlich wie bei Typ- und Funktionsdeklarationen. Typannotationen f¨ur Funktionen oder (wiederhol-te) type-Annotationen f¨ur (mehrere) Typen sind umst¨andlich und deswegen sollte ein syntaktisch getrennter Import von Typen und Funktionen erwogen werden, etwa in der folgenden Form:

import Seq[nat] only typeseq fun:: ♦ . . .

Uberlagerungen zwischen Typen und Funktionen w¨¨ aren auf diese Weise leich-ter kontrollier- und erkennbar. Der selektive Import von Funktionen, ohne

¨

uberlagerteTypen mit zu importieren, die gar nichts mit der Funktion zu tun haben, erfordert Typannotationen, die man lieber nur zur Trennung ¨ uberla-gerter Funktionen verwenden w¨urde.

7.2.3 Generische Instanz

Die Typannotation von instanziiert importierten Funktionen erfolgt mit ih-ren instanziierten Typen. Wie sollen aber Typannotationen f¨ur importierte Funktionen angegeben werden, wenn die formalen Parameter im generischen (oder im zu konstruierenden) Namensraum nicht zur Verf¨ugung stehen? In Opal sind die Typannotationen entsprechend beschr¨ankt:

import Seqonly seq: type ♦: seq import Seqonly ft: seq→α

- legal - illegal

Dadurch lassen sich insbesondere die ¨uberlagerten Funktionen seqvom Typ α → seq und α×α → seq (aus Abschnitt 5.4.3) nicht getrennt generisch importieren.

Die Angabe einer instanziierten Typannotation ist – ebenso wie die direkte Instanzannotation – in Opal f¨ur generische Funktionsnamen nicht zul¨ as-sig; lediglich partielle Typnamen, in denen formale Parameter weggelassen werden, sind f¨ur Typannotationen geeignet. Aber selbst der (inOpal unzu-l¨assige) partielle Name → seq w¨urde sowohl auf den Typ α×α → seq als auch auf α →seq passen. (Nur × →seq w¨urde nicht auf α →seq passen.)

Wenn man bei generischen Importen – wie ¨ublich – vollst¨andig von den Na-men formaler Parameter abstrahieren und trotzdem jede Funktionalit¨at an-notieren k¨onnen m¨ochte, dann ist das elegant mit einem extra Platzhalter f¨ur formale Parameter m¨oglich. Interessanterweise kann der Platzhalter f¨ur alle Parameter gleich gew¨ahlt werden, da Funktionalit¨aten von ¨ uberlager-ten Funktionen einer Struktur f¨ur keine Instanz zusammenfallen (Abschnitt 5.4.2), also auch nicht f¨ur einehypothetische Instanz aktueller Parameter mit gleichen Namensinstanzen!

Als Syntax f¨ur diesen Platzhalter wird wieder der Unterstrich gew¨ahlt, der damit seine Bedeutung als beliebige Namensinstanz (Abschnitt 6.1.2) zumin-dest f¨ur generische Importe einb¨ußt. (Denkbar w¨are es auch, ein anderes Schl¨usselsymbol f¨ur die formalen Parameter zu w¨ahlen. Eine beliebige Na-mensinstanz ist allgemeiner als ein formaler Parameter und sollte daher l¨ an-ger sein; z.B. w¨aren auch zwei Unterstriche f¨ur Namensinstanzen bzw. ein Punkt f¨ur formale Parameter geeignet.)

Die Typannotation →seqwird nun mit der Interpretation des Unterstrichs als formaler Parameter eindeutig und jede generische Funktionalit¨at kann so bei Bedarf immer eindeutig notiert werden. Instanzannotationen innerhalb der Typen sind nat¨urlich erlaubt:

import Seqonly ft: seq→

import Setonly # : set[ , : rel[ ]]→nat

Die in den Typannotationen verwendeten Namen m¨ussen nat¨urlichnicht im-portiert werden. Diese Namen sind im Namensraum der imim-portierten Struk-tur bekannt und dienen lediglich zur Identifizierung des tats¨achlich zu im-portierenden Namens.

Die Notation Set[ , ] entspricht einer hypothetischen Instanz, w¨ahrend se-mantisch die importierten Namen bez¨uglich der formalen Parameter poly-morph bleiben. Der Versuch einer (durch Typannotationen indirekten) In-stanziierung mit monomorphen Namen, die sich vom Platzhalter f¨ur die for-malen Parameter unterscheiden, w¨urde zu einem Identifizierungsfehler f¨ uh-ren. Generische Namen werden immer mit ihrer generischen Instanz impor-tiert.

Um¨uberlagerte Strukturen generisch getrennt zu importieren, kann man typ-annotierte Platzhalter oder nur die Typen in der Importinstanz angeben:

import Set[ :type, : rel[ ]] only set import Set[type,rel[ ]] only set

- oder

Eine Instanz S[type, : ] korrespondiert zur Parametrisierung S[α, β: α].

Welche Parametrisierung passt zu T[type, ]? Steht also der Platzhalter f¨ur die Namensinstanz des zweiten Parameters oder f¨ur seinen Typ? Das kann man beliebig festlegen oder Eindeutigkeit per Doppelpunkt erreichen:

T[type, : ] oderT[type, : ]. Ganz allgemein ist ein f¨uhrender oder folgen-der Doppelpunkt eine geeignete und minimale Annotation, um Typen und Funktionen zu unterscheiden!