Daher kenne ich zwei Hauptstrategien für einen höherrangigen Polymorphismus in einer Sprache:
- Polymorphismus im System-F-Stil, bei dem Funktionen explizit typisiert werden und die Instanziierung explizit über die Typanwendung erfolgt. Diese Systeme können beeindruckend sein.
- Subtypisierungsbasierter Polymorphismus, wobei ein polymorpher Typ ein Subtyp aller seiner Instanziierungen ist. Um eine entscheidbare Subtypisierung zu haben, muss der Polymorphismus prädikativ sein. Dieses Dokument enthält ein Beispiel für ein solches System.
Einige Sprachen, wie Haskell, weisen jedoch einen unprädikativen höherrangigen Polymorphismus ohne explizite Typanwendungen auf.
Wie ist das möglich? Wie kann die Typprüfung "wissen", wann ein Typ ohne explizite Instanziierung oder Umwandlung und ohne den Begriff der Subtypisierung instanziiert werden muss?
Oder ist Typchecking in einem solchen System überhaupt entscheidbar? Ist dies ein Fall, in dem eine Sprache wie Haskell etwas Unentscheidbares implementiert, das für die Anwendungsfälle der meisten Menschen funktioniert?
BEARBEITEN:
Um es klar auszudrücken, ich interessiere mich für die Verwendung und nicht für Definitionen von polymorph typisierten Werten.
Nehmen wir zum Beispiel an, wir haben:
f : forall a . a -> a
g : (forall a . a -> a) -> Int
val = (g f, f True, f 'a')
Wie können wir wissen, dass wir instanziieren müssen, f
wenn es angewendet wird, aber nicht, wenn es als Argument angegeben wird?
Oder um uns von Funktionstypen zu trennen:
f : forall a . a
g : (forall a . a) -> Int
val = (g f, f && True, f + 0)
Hier können wir nicht einmal zwischen der Verwendung f
als Anwenden und Übergeben unterscheiden: Es wird instanziiert, wenn es als Argument an &&
und übergeben wird +
, aber nicht g
.
Wie kann ein theoretisches System diese beiden Fälle ohne die magische Regel "Sie können jeden polymorphen Typ in seine Instanz konvertieren" unterscheiden? Oder können wir mit einer solchen Regel wissen, wann wir sie anwenden müssen, um die Entscheidbarkeit zu bewahren?
g
dass sie einen Polytyp erwartet und die Instanziierung von verhindert f
.
\f -> (f True, f 'a')
wird keine Typprüfung durchgeführt, auch wenn ihr der Typ zugewiesen werden kann(forall t. t->t) -> (Bool, Char)