'Wie man Funktoren höherer Ordnung richtig benutzt?' oder "Wie viel Spaß mit Funsigs haben?"

8

Motivation

Für das Leben von mir kann ich nicht herausfinden, wie man Funktoren höherer Ordnung einsetzt SML / NJ zu irgendeinem praktischen Ende.

Laut der SML / NJ-Dokumente zu den speziellen Funktionen der Implementierung , Es sollte möglich sein, einen Funktor als Argument für einen anderen mit Hilfe von anzugeben das funsig -Schlüsselwort. Also, eine Signatur gegeben

%Vor%

Wir sollten in der Lage sein, einen Funktor anzugeben, der ein befriedigendes Modul erzeugt SIG , wenn es auf eine Struktur angewendet wird, die eine Signatur SIG' erfüllt. Z. B.

%Vor%

Wenn Fn auf diese Weise deklariert ist, sollten wir dann (in der Lage sein, einen anderen zu definieren) Funktor, der diesen Funktor als Argument akzeptiert. Das heißt, wir können ein Modul definieren das wird über ein anderes parametrisiertes Modul parametrisiert und verwendet vermutlich das letzteres innerhalb des ersteren; Also:

%Vor%

In der Theorie sieht alles gut aus, aber ich kann mir nicht vorstellen, wie ich es wirklich nutzen kann dieses Muster.

Beispielprobleme

Hier sind zwei Beispiele, wo ich versucht habe, dieses Muster zu verwenden, nur um zu finden es ist nicht praktikabel:

Erster Versuch

Für meinen ersten Versuch, nur herumspielen, habe ich versucht, einen Funktor zu machen, der das würde Nehmen Sie einen Funktor, der eine geordnete Menge implementiert, und erstellen Sie ein Modul für den Handel mit Mengen von ganzen Zahlen (nicht wirklich nützlich, aber es würde Sie Sets parametrisieren lassen eines bestimmten Typs über verschiedene Set-Implementierungen). Ich kann das definieren folgende Strukturen, und sie werden kompilieren (mit Standard ML von New Jersey v110.7 ):

%Vor%

Aber wenn ich tatsächlich versuche, IntSetFn auf einen Funktor anzuwenden, der den SET_FN funsig, es parst einfach nicht:

%Vor%

Zweiter Versuch

Mein zweiter Versuch scheitert auf zwei Arten.

Ich habe eine Struktur von verschachtelten Modulen definiert, die polymorphe und monomorphe Stacks ( die Quelldatei , für Neugierige). Zu implementieren Sie einen monomorphen Stapel, tun Sie

%Vor%

und so weiter. Es scheint soweit zu funktionieren. Jetzt möchte ich ein Modul definieren, das parametrisiert über diesen Funktor. Also habe ich einen Spaß für die Collect.Stack.Mono funktor (was in meinem Repo zu sehen ist). Dann, nach dem Muster oben angegeben, habe ich versucht, das folgende Testmodul zu definieren:

%Vor%

Aber das wird nicht kompilieren! Ich erhalte einen Typfehler:

%Vor%

Im funktor T verwende ich anscheinend genau die gleiche Instanziierung Muster, das auf der obersten Ebene perfekt funktioniert. Was vermisse ich?

Leider ist das nicht das Ende meiner Pannen. Jetzt entferne ich die Linie verursacht den Typ Fehler, verlassen,

%Vor%

Dies wird gut übersetzt:

%Vor%

Aber ich kann das Modul nicht wirklich instantiieren! Anscheinend die Pfadzugriffssyntax wird für Funktoren höherer Ordnung nicht unterstützt?

%Vor%

Ich bin verloren.

Fragen

Ich habe drei verwandte Fragen:

  1. Gibt es ein Grundprinzip von Funktoren höherer Ordnung in SML / NJ, das ich bin? fehlt oder ist es nur ein unvollständig, unbeholfen implementiertes Merkmal der Sprache?
  2. Wenn letzteres, wo kann ich mich für eleganter und praktikabler höherer Ordnung wenden Funktoren? (Hoffentlich ein SML, aber ich werde bei Bedarf in OCaml eintauchen.)
  3. Gibt es vielleicht einen anderen Ansatz, den ich ergreifen sollte, um diese Arten zu erreichen? von Effekten, die Funktoren höherer Ordnung alle zusammen vermeiden?

Vielen Dank im Voraus für Antworten, Tipps oder Folgefragen!

    
Shon Feder 04.09.2016, 04:49
quelle

1 Antwort

7

In Bezug auf Ihren ersten Versuch lautet die richtige Syntax für die Anwendung Ihres IntSetFn -Funktors:

%Vor%

Gleiches gilt für Ihre Anwendung des Test -Funktors im zweiten Versuch:

%Vor%

Das sollte die Syntaxfehler beheben.

Der Typfehler, den Sie bekommen, wenn Sie versuchen, Ihre Stack-Struktur S in funktor T zu verwenden, hängt mit der Art zusammen, wie Sie MONO_STACK funsig definiert haben:

%Vor%

Dies sagt nur, dass es eine MONO_STACK -Struktur mit einem vollständig abstrakten elem -Typ zurückgibt. Es heißt nicht, dass sein elem type identisch mit E.elem ist. Demnach könnte ich einen Funktor wie

übergeben %Vor%

zu deinem Funktor T . Daher darf das Typsystem innerhalb von T nicht den Typ S.elem = int annehmen, und daher erhalten Sie einen Typfehler.

Um dies zu beheben, müssen Sie den MONO_STACK funsig wie folgt verfeinern:

%Vor%

Das sollte den Typfehler beseitigen.

[Bearbeiten]

Wie für Ihre Fragen:

  1. Höherwertige Funktoren sind in SML / NJ etwas komisch syntaktisch, weil sie zu 100% kompatibel mit einfachem SML bleiben, das den Namespace von Funktoren von dem für Strukturen trennt. Wäre das nicht der Fall, dann gäbe es keine Notwendigkeit für Funsigs als separaten Namensraum (und anderen syntaktischen Barock), und die Sprache der Signaturen könnte einfach um Funktortypen erweitert werden.

  2. Moscow ML ist ein weiterer SML-Dialekt mit einer höheren Modul-Erweiterung, der das Kompatibilitätsproblem etwas eleganter löst (und expressiver ist). Es gab auch (jetzt meistens tot) ALice ML, noch einen anderen SML-Dialekt mit Funktoren höherer Ordnung, die einfach die peinliche Namensraumtrennung fallen ließen. OCaml hatte diese Einschränkung natürlich nicht, daher sind die Module höherer Ordnung auch syntaktischer.

  3. Der Ansatz scheint in Ordnung.

Andreas Rossberg 04.09.2016, 06:46
quelle

Tags und Links