2012-04-04 55 views
4

準引號允許在編譯期間生成AST代碼,但它會在生成準引號的地方插入生成的代碼。是否有可能以任何方式在其他地方插入編譯時生成的代碼?例如,在特定的模塊文件中,這些文件與編寫QQ的模塊文件不同?這取決於硬編碼的模塊結構,但沒關係。如何在Haskell編譯期間在不同位置包含代碼?

如果QQ無法做到這一點,但任何人都知道以不同的方式實現它,我很樂意提供建議。

+4

我認爲這會有所幫助,如果你可以提到你試圖用這個來實現。從技術上講,TH可以運行任意IO,包括讀取和解析正在編譯的模塊,所以你可以從不同的地方甚至不同的模塊中獲取東西,但是細節取決於你想要做什麼。 – hammar 2012-04-05 00:21:22

回答

4

要回答這個問題,有必要了解一個準報價是什麼。從GHC Documentation,準加引號是

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

這是一個值,它是從一個任意字符串到一個或多個的ExpQPatQTypeQDecQ,這是表達式的模板哈斯克爾表示解析器,模式,類型和聲明。

當您使用準引號時,GHC將解析器應用於字符串以創建ExpQ(或其他類型),然後在生成的模板haskell表達式中拼接以產生實際值。

這聽起來像你要求做的是分離quasiquote解析和拼接,以便您可以訪問TH表達式。然後,您可以將該表達式導入另一個模塊並將其自行拼接。

瞭解準報價單的類型,很明顯這是可能的。通常情況下,你使用QQ作爲

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

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

相反,你可以自己提取解析器,得到了TH的表達,後來拼接它:

-- 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) 

當然,如果你在寫這一切你自己,您可以跳過準引號,直接使用解析器和模板Haskell。這兩種方法幾乎都是一樣的。