Ist es möglich, eine Funktion mit Template Haskell zu definieren? Zum Beispiel
%Vor% Ich habe auch eine Map [Char] Int
.
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.
Sie können dies mit zwei Dateien tun:
Eine "Maker" -Datei: Maker.hs
:
und die Hauptdatei: Main.hs
:
In diesem Fall ist function
vom Typ [Char] -> Int
und wird wie folgt kompiliert:
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>
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 .
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:
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.
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:
("five",5)
usw. führen wir eine Match
Anweisung ein:
%Vor%
Jetzt können wir das einfach mit \(a,b)
:
und verwenden Sie dann map
, um über alle Elemente zu iterieren:
mit items
die Liste der Tupel, für die wir Fälle generieren wollen. Jetzt sind wir fertig:
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
.
Der Hersteller ist hier eine Art Funktion, die die Funktion macht / konstruiert.
Seien Sie sich bewusst, dass der Compiler zwischen den Dollarklammern $()
bewertet. Wenn Sie zum Beispiel eine unendliche Liste verwenden würden:
Dies wird weiterhin Speicher für den abstrakten Syntaxbaum reservieren und letztendlich keinen Speicher mehr haben. Der Compiler nicht erweitert zur Laufzeit einen AST.
Tags und Links haskell template-haskell