2011-12-15 41 views
36

如您所知,模板Haskell用於在編譯時以編程方式生成各種AST拼接。查看由模板生成的代碼的首選方法Haskell

但是,拼接通常可能非常不透明,並且通常很難辨別拼接實際產生的內容。如果您運行拼接單元的Q monad,並且拼接格式良好,則會生成AST的生成片段,但由於其非結構化佈局,此表示形式可能非常難以理解。

將一段TH生成的AST轉換爲類似於正常Haskell代碼的首選方法是什麼,以便可以輕鬆讀取和理解代碼?是否可以重新構建源代碼給定Dec值?是否需要閱讀GHC核心代碼?有沒有一種方法可以至少構建AST,使其變得更加可讀(除了例如pretty-show包以外)?

回答

22

您可以使用pprintpprLanguage.Haskell.TH.Ppr(與Language.Haskell.TH自動導入):

GHCi> expr <- runQ [| \f g x -> f (x*2 + 3) . g |] 
GHCi> putStrLn $ pprint expr 
\f_0 g_1 x_2 -> f_0 ((x_2 GHC.Num.* 2) GHC.Num.+ 3) GHC.Base.. g_1 

它不漂亮,但它有效的Haskell。您應該能夠通過從Prelude名稱中去除模塊前綴來使輸出更好(儘管您可能需要小心只刪除預期的前綴;畢竟Foo.*是完全有效的中綴運算符)。

46

您是否在尋找編譯器的-ddump-splices標誌?

+2

是,這種輸出的正是我要找的!但是這也可以在一個程序中完成,只給出一個語法樹,還是需要調用編譯器? – dflemstr 2011-12-15 14:25:32

+1

注意:確保在運行此操作之前刪除.hi和.o文件以獲取乾淨的版本,否則您將無法獲得任何stderr輸出。 – RussellStewart 2014-09-18 23:27:54

1

爲補充ehird answer

注意,在一般使用直接從runQ GHCI 可能無法正常工作 (使用reify操作, 參見comments above the runQ declaration例如爲:TH發電機)。

如果失敗了,你可以pprint(或show),變換介紹則字符串表達式stringE拼接作爲參數傳遞給putStrLn

> putStrLn $(stringE . pprint =<< [| \f g x -> f (x*2 + 3) . g |]) 
\f_0 g_1 x_2 -> f_0 ((x_2 GHC.Num.* 2) GHC.Num.+ 3) GHC.Base.. g_1