Bei der Arbeit wurde ich beauftragt, einige Typinformationen über eine dynamische Sprache abzuleiten. Ich schreibe Folgen von Anweisungen in verschachtelte let
Ausdrücke um, wie folgt:
return x; Z => x
var x; Z => let x = undefined in Z
x = y; Z => let x = y in Z
if x then T else F; Z => if x then { T; Z } else { F; Z }
Da ich von allgemeinen Typinformationen ausgehe und versuche, spezifischere Typen abzuleiten, sind Verfeinerungstypen die natürliche Wahl. Beispielsweise gibt der bedingte Operator eine Vereinigung der Typen seiner wahren und falschen Zweige zurück. In einfachen Fällen funktioniert es sehr gut.
Ich bin jedoch auf einen Haken gestoßen, als ich versucht habe, auf Folgendes zu schließen:
function g(f) {
var x;
x = f(3);
return f(x);
}
Welches wird umgeschrieben in:
\f.
let x = undefined in
let x = f 3 in
f x
HM würde und folglich . Der tatsächliche Typ, auf den ich schließen möchte, ist:
Ich verwende bereits funktionale Abhängigkeiten, um den Typ eines überladenen +
Operators aufzulösen. Daher dachte ich, es sei eine natürliche Wahl, sie zum Auflösen des Typs von f
innerhalb zu verwenden g
. Das heißt, die Typen von f
in all seinen Anwendungen zusammen bestimmen eindeutig den Typ von g
. Wie sich jedoch herausstellt, eignen sich Fundeps nicht besonders gut für eine variable Anzahl von Quelltypen.
Wie auch immer, das Zusammenspiel von Polymorphismus und Verfeinerungstypisierung ist problematisch. Gibt es einen besseren Ansatz, den ich vermisse? Ich verdaue derzeit "Verfeinerungstypen für ML" und würde mich über mehr Literatur oder andere Hinweise freuen.
quelle