模板 Haskell 和 Quasiquotes 的語法
模板 Haskell 由 -XTemplateHaskell
GHC 擴充套件啟用。此擴充套件啟用了本節中進一步詳述的所有語法功能。有關 Template Haskell 的完整詳細資訊,請參見使用者指南 。
接頭
-
splice 是一個由 Template Haskell 啟用的新語法實體,寫為
$(...)
,其中(...)
是一個表示式。 -
$
和表示式的第一個字元之間不能有空格; 和模板 Haskell 覆蓋了$
運算子的解析 - 例如,f$g
通常被解析為($) f g
,而啟用了 Template Haskell,它被解析為拼接。 -
當拼接出現在頂層時,可以省略
$
。在這種情況下,拼接表示式是整行。 -
splice 表示在編譯時執行以生成 Haskell AST 的程式碼,並且該 AST 被編譯為 Haskell 程式碼並插入到程式中
-
拼接可以代替:表示式,模式,型別和頂級宣告。在每種情況下,拼接表達的型別分別是
Q Exp
,Q Pat
,Q Type
,Q [Decl]
。請注意,宣告拼接可能只出現在頂層,而其他拼接可能分別出現在其他表示式,模式或型別中。
表示式引用(注意: 不是 QuasiQuotation)
-
表示式引用是一個新的語法實體,寫成以下之一:
[e|..|]
或[|..|]
-..
是一個表示式,引用的型別為Q Exp
;[p|..|]
-..
是一種模式,引用的型別為Q Pat
;[t|..|]
-..
是一個型別,引用的型別為Q Type
;[d|..|]
-..
是一個宣告列表,引用的型別為Q [Dec]
。
-
表示式引用採用編譯時程式並生成該程式表示的 AST。
-
在沒有拼接的情況下在引用中使用值(例如
\x -> [| x |]
)對應於\x -> [| $(lift x) |]
的語法糖,其中lift::Lift t => t -> Q Exp
來自類
class Lift t where
lift::t -> Q Exp
default lift::Data t => t -> Q Exp
鍵入的拼接和引用
-
型別拼接與之前提到的(無型別)拼接類似,並且寫為
$$(..)
,其中(..)
是表示式。 -
如果
e
的型別為Q (TExp a)
,則$$e
的型別為a
。 -
輸入的引文采用
[||..||]
的形式,其中..
是a
型別的表示式; 結果引號的型別為Q (TExp a)
。 -
鍵入的表示式可以轉換為無型別的表示式:
unType::TExp a -> Exp
。
QuasiQuotes
-
QuasiQuotes 概括了表示式引用 - 之前,表示式引用使用的解析器是固定集(
e,p,t,d
)之一,但 QuasiQuotes 允許定義自定義解析器並在編譯時使用它來生成程式碼。準引用可以出現在與常規引用相同的上下文中。 -
準引用被寫為
[iden|...|]
,其中iden
是Language.Haskell.TH.Quote.QuasiQuoter
型別的識別符號。 -
QuasiQuoter
簡單地由四個解析器組成,每個解析器可以出現一個不同的上下文:
data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
quotePat :: String -> Q Pat,
quoteType::String -> Q Type,
quoteDec :: String -> Q [Dec] }
名稱
-
Haskell 識別符號由
Language.Haskell.TH.Syntax.Name
型別表示。名稱形成抽象語法樹的葉子,表示模板 Haskell 中的 Haskell 程式。 -
當前在範圍內的識別符號可以變為具有以下任一名稱的名稱:
'e
或'T
。在第一種情況下,e
在表示式範圍內被解釋,而在第二種情況下,T
在型別範圍內(回想一下型別和值建構函式可以在 Haskell 中沒有歧義地共享名稱)。