Simon hat im Grunde genommen recht, was die Erweiterung betrifft. Wir wissen ziemlich genau, wie die Semantik moderner funktionaler Sprachen aussieht, und es handelt sich tatsächlich um relativ kleine Variationen - sie repräsentieren jeweils leicht unterschiedliche Übersetzungen in eine monadische Metasprache. Sogar eine Sprache wie Scheme (eine dynamisch typisierte imperative Sprache höherer Ordnung mit erstklassiger Kontrolle) hat eine Semantik, die der von ML und Haskell ziemlich nahe kommt.
Aus denotational Sicht, können Sie , indem sie eine ziemlich einfache Domain - Gleichung für die Semantik von Schema beginnen - nennen es . Leute konnten und haben solche Gleichungen in den späten 70ern / frühen 80ern gelöst, also ist das nicht so schlimm. In ähnlicher Weise gibt es auch für Scheme eine relativ einfache operationale Semantik. (Beachten Sie, dass wenn ich "Schema" sage, ich untypisierte Lambda-Rechnung plus Fortsetzungen plus Zustand meine, im Gegensatz zu dem tatsächlichen Schema, das ein paar Warzen hat, wie es alle realen Sprachen tun.)V
Aber um zu einer Kategorie zu gelangen, die für die Interpretation moderner typisierter funktionaler Sprachen geeignet ist, wird es ziemlich beängstigend. Im Grunde konstruieren Sie eine ultrametrisch angereicherte Kategorie von partiellen Äquivalenzbeziehungen über diesen Bereich. (Als Beispiel siehe Birkedal, Stovring und Thamsborgs "Realisierbarkeitssemantik des parametrischen Polymorphismus, allgemeine Referenzen und rekursive Typen".) Leute, die operationale Semantik bevorzugen, kennen dieses Material als schrittindizierte logische Beziehungen. (Siehe zum Beispiel Ahmed, Dreyer und Rossbergs "State-Dependent Representation Independence".) In beiden Fällen sind die verwendeten Techniken relativ neu.
Der Grund für diese mathematische Komplexität ist, dass wir in der Lage sein müssen, den parametrischen Polymorphismus und den Zustand höherer Ordnung gleichzeitig zu interpretieren. Aber wenn Sie dies getan haben, sind Sie im Grunde genommen zu Hause frei, da diese Konstruktion alle harten Teile enthält. Jetzt können Sie ML- und Haskell-Typen über die üblichen monadischen Übersetzungen interpretieren. MLs strenger, effektiver Funktionsraum a -> b
übersetzt sich in right>⟨a⟩→T⟨b⟩⟨a⟩→⟨b⟩T(A)⟨a⟩a
→
Nach der Gleichungstheorie ist es durchaus gerechtfertigt, beide Sprachen syntaktische Variationen voneinander zu nennen, da beide Sprachen durch Übersetzungen in leicht unterschiedliche Teilmengen derselben Sprache beschrieben werden können.
Der Unterschied im Spielgefühl zwischen ML und Haskell ergibt sich tatsächlich aus den intensiven Eigenschaften der beiden Sprachen, dh der Ausführungszeit und dem Speicherverbrauch. ML hat ein kompositorisches Leistungsmodell (dh die Zeit- / Raumkosten eines Programms können aus den Zeit- / Raumkosten seiner Untertitel berechnet werden), wie dies bei einer echten Call-by-Name-Sprache der Fall wäre. Tatsächlich wird Haskell mit Call-by-Need implementiert, einer Art Memoization, und daher ist seine Leistung nicht kompositorisch. Wie lange ein an eine Variable gebundener Ausdruck für die Auswertung benötigt, hängt davon ab, ob er zuvor verwendet wurde oder nicht. Dies ist in der Semantik, auf die ich oben angespielt habe, nicht modelliert.
Wenn Sie die Intensitätseigenschaften ernst nehmen möchten, zeigen ML und Haskell ernstere Unterschiede. Es ist wahrscheinlich immer noch möglich, eine gemeinsame Metasprache für sie zu entwickeln, aber die Interpretation der Typen wird sich in Bezug auf die proof-theoretische Idee der Fokussierung systematischer unterscheiden . Ein guter Ort, um dies zu lernen, ist Noam Zeilbergers Doktorarbeit.