2012-04-04 5 views
4

Quasi-Anführungszeichen ermöglichen das Generieren von AST-Code während Kompilierungen, aber es fügt generierten Code an der Stelle ein, an der Quasi-quote geschrieben wurde. Ist es in irgendeiner Weise möglich, den generierten Code für die Kompilierung an anderer Stelle einzufügen? Zum Beispiel in bestimmten Moduldateien, die sich von denen unterscheiden, in denen QQ geschrieben wurde? Es hängt von einer fest codierten Modulstruktur ab, aber das ist in Ordnung.Wie kann Code an verschiedenen Orten während der Zusammenstellung in Haskell eingefügt werden?

Wenn das mit QQ nicht möglich ist, aber jeder weiß, dass es anders geht, bin ich offen für Vorschläge.

+4

Ich denke, es wäre hilfreich, wenn Sie erwähnen könnten, was Sie damit erreichen wollen. Technisch gesehen kann TH ein beliebiges IO ausführen, einschließlich des Lesens und Parsens des zu kompilierenden Moduls, so dass Sie Daten von verschiedenen Orten oder sogar verschiedenen Modulen abrufen können, aber die Details hängen davon ab, was Sie tun möchten. – hammar

Antwort

4

Um dies zu beantworten, ist es hilfreich zu wissen, was ein Quasi-Quotierer ist. Vom GHC Documentation, ein quasi-quoter ein Wert von

data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp, 
           quotePat :: String -> Q Pat, 
           quoteType :: String -> Q Type, 
           quoteDec :: String -> Q [Dec] } 

ist Das heißt, es ist ein Parser von einem beliebigen String zu einem oder mehreren der ExpQ, PatQ, TypeQ und DecQ, die Template Haskell Darstellungen von Ausdrücken sind , Muster, Typen und Deklarationen.

Wenn Sie ein Quasi-Anführungszeichen verwenden, wendet GHC den Parser auf den String an, um einen ExpQ (oder einen anderen Typ) zu erstellen, und spleißt dann den resultierenden Template-Hakel-Ausdruck, um einen tatsächlichen Wert zu erzeugen.

Es hört sich so an, als ob Sie das Quasi-Parsen und Splicing trennen, damit Sie Zugriff auf den TH-Ausdruck haben. Dann können Sie diesen Ausdruck in ein anderes Modul importieren und dort selbst spleißen.

Wenn man den Typ eines Quasi-Quotiers kennt, ist es offensichtlich, dass dies möglich ist. Normalerweise verwenden Sie einen QQ als

-- file Expr.hs 
eval :: Expr -> Integer 
expr = QuasiQuoter { quoteExp = parseExprExp, quotePat = parseExprPat } 

-- file Foo.hs 
import Expr 
myInt = eval [expr|1 + 2|] 

Stattdessen können Sie den Parser selbst extrahieren, eine TH-Expression erhalten, und es splice später:

-- file Foo.hs 
import Expr 

-- run the QQ parser 
myInt_TH :: ExpQ 
myInt_TH = quoteExp expr "1 + 2" 

-- file Bar.hs 
import Foo.hs 

-- run the TH splice 
myInt = $(myInt_TH) 

Natürlich, wenn Sie all diese Texte selbst schreiben, Sie können die Quasi-Anführungszeichen überspringen und einen Parser und Template Haskell direkt verwenden. Es ist so oder so ähnlich.

Verwandte Themen