Ich habe kürzlich festgestellt, dass eine Reihe von Problemen, die ich vor einigen Jahren beim Versuch hatte, verschiedene mathematische Theorien in Java zu implementieren, darauf zurückzuführen sind, dass das Typisierungssystem in Java nicht stark genug ist, um die gesamte Martin-Löf-abhängige Typentheorie zu modellieren .
Vor Java 5 und Generika war die einzige Typentheorie, die Sie durchführen konnten, Klassen und Schnittstellen, die Ihnen beliebige Typen liefern, die aus den Bodentypen aufgebaut int
sind double
, char
und so weiter, indem Sie Produkt- und Funktionstypen verwenden. Sie können auch rekursive Typen wie List
s erstellen , allerdings nicht auf einheitliche Weise.
Mit Generika können Sie ein bisschen mehr tun. Sie können jetzt List<T>
als Funktion
und so erhalten wir Typen höherer Ordnung.
Dies ist jedoch nicht das Ende der Geschichte. Mit einem generischen Trick können wir einige abhängige Produkttypen modellieren . Zum Beispiel können wir Typen der Form mithilfe der Syntax definieren
public interface f<T extends f<T>>
{
// We can now refer to T as much as we like
// inside the class. T has type f<T>.
}
Als Beispiel können wir die zugrunde liegende Grundstruktur eines Monoids (aber nicht die Assoziativitäts- und Unitalitätsbedingungen) unter Verwendung eines Ausdrucks vom Typ modellieren : Typ T × ( T → T → T ) (dh eine Menge T mit einer Bezeichnung Einheitselement und eine binäre Operation an T ). Mit Java-Generika können wir diesen Typ modellieren:
public interface MonoidElement<T extends MonoidElement<T>>
{
public T unit();
public T mul(T op1, T op2);
}
Wenn wir jedoch versuchen, kompliziertere Konzepte zu modellieren, bricht die Typentheorie zusammen.
Gibt es eine einfache Beschreibung des MLTT-Fragments, das den Typen entspricht, die im Java-Typisierungssystem erstellt werden können?