Erzeugen Sie eine Funktion mit Template Haskell

8

Ist es möglich, eine Funktion mit Template Haskell zu definieren? Zum Beispiel

%Vor%

Ich habe auch eine Map [Char] Int .

%Vor%

Wie kann ich Funktionen hinzufügen

? %Vor%

zur Kompilierzeit mit Template Haskell und dem Map ? Es erscheint ziemlich albern, Template Haskell für diesen Zweck zu verwenden, aber ich würde es trotzdem gerne wissen.

    
user2512324 29.05.2015, 12:59
quelle

2 Antworten

3

Sie können dies mit zwei Dateien tun:

Eine "Maker" -Datei: Maker.hs :

%Vor%

und die Hauptdatei: Main.hs :

%Vor%

In diesem Fall ist function vom Typ [Char] -> Int und wird wie folgt kompiliert:

%Vor%

Es ist also so, als hätten Sie geschrieben:

%Vor%

selbst. Offensichtlich wird sich das für zwei oder drei Fälle nicht auszahlen, aber wie Sie selbst in der Frage geschrieben haben, wenn Sie Tausende von Fällen oder eine Liste von Elementen verwenden möchten, die durch Listenverständnis generiert werden, beginnt sich das auszuzahlen. p>

Vorlage erstellen Haskell selbst

In diesem Abschnitt soll kurz beschrieben werden, wie Sie Vorlage Haskell selbst schreiben. Dieses Tutorial ist nicht "eine vollständige Einführung in ..." : Es gibt andere Techniken, dies zu tun.

Um Template Haskell zu schreiben, können Sie zuerst ein paar Ausdrücke ausprobieren und dann versuchen, sie mit map , fold , etc. zu verallgemeinern .

Analysiere den AST-Baum

Sehen Sie sich zuerst einmal an, wie Haskell einen bestimmten Ausdruck selbst analysieren würde. Sie können dies mit runQ und Klammern [| ... |] mit ... dem Ausdruck, den Sie analysieren möchten, machen. Also zum Beispiel:

%Vor%

Der AST lautet also:

%Vor%

Nun haben wir abgeleitet den abstrakten Syntaxbaum (AST) von diesem Ausdruck. Ein Hinweis ist, die Ausdrücke generisch genug zu machen. Verwenden Sie zum Beispiel mehrere Fälle im Block case , da die Verwendung eines einzelnen Falls Ihnen nicht sagt, wie Sie Ihrem Ausdruck einen zweiten hinzufügen sollten. Jetzt möchten wir einen solchen abstrakten Syntaxbaum selbst erstellen.

Erstellen Sie Variablennamen

Ein erster Aspekt sind die Variablen, wie VarP x_0 und VarE x_0 . Sie können sie nicht einfach kopieren und einfügen . Hier ist x_0 ein Name. Um sicherzustellen, dass Sie keinen bereits vorhandenen Namen verwenden, können Sie newName verwenden. Jetzt können Sie den folgenden Ausdruck erstellen, um ihn vollständig zu replizieren:

%Vor%

Generalisieren Sie die Funktion

Offensichtlich sind wir nicht daran interessiert, einen festen abstrakten Syntaxbaum zu konstruieren, sonst hätten wir ihn selbst schreiben können. Nun, der Punkt ist, dass Sie eine oder mehrere Variablen einführen und über diese Variablen nachdenken. Für jedes Tupel ("five",5) usw. führen wir eine Match Anweisung ein:

%Vor%

Jetzt können wir das einfach mit \(a,b) :

verallgemeinern %Vor%

und verwenden Sie dann map , um über alle Elemente zu iterieren:

%Vor%

mit items die Liste der Tupel, für die wir Fälle generieren wollen. Jetzt sind wir fertig:

%Vor%

Jetzt können Sie einfach return weglassen, weil die Bibliothek für alle diese Elemente Kleinbuchstaben hat. Sie können außerdem versuchen, den Code ein wenig aufzuräumen (wie zum Beispiel (NormalB (LitE (IntegerL b))) bis (NormalB $ LitE $ IntegerL b) , usw.); zum Beispiel mit hlint .

%Vor%

Der Hersteller ist hier eine Art Funktion, die die Funktion macht / konstruiert.

Achten Sie auf unendliche Listen

Seien Sie sich bewusst, dass der Compiler zwischen den Dollarklammern $() bewertet. Wenn Sie zum Beispiel eine unendliche Liste verwenden würden:

%Vor%

Dies wird weiterhin Speicher für den abstrakten Syntaxbaum reservieren und letztendlich keinen Speicher mehr haben. Der Compiler nicht erweitert zur Laufzeit einen AST.

    
Willem Van Onsem 07.06.2015, 20:21
quelle
2

Ja

%Vor%

Und dann

%Vor%     
mb14 07.06.2015 20:35
quelle

Tags und Links