如何在Haskell中编译期间在不同的位置包含代码?
准引号允许在编译期间生成AST代码,但它会在编写准引号的位置插入生成的代码。是否可以以任何方式将编译时生成的代码插入其他地方?例如,在特定的模块文件中,哪些文件与写QQ的文件不同?这取决于硬编码的模块结构,但这没关系如何在Haskell中编译期间在不同的位置包含代码?,haskell,abstract-syntax-tree,template-haskell,Haskell,Abstract Syntax Tree,Template Haskell,准引号允许在编译期间生成AST代码,但它会在编写准引号的位置插入生成的代码。是否可以以任何方式将编译时生成的代码插入其他地方?例如,在特定的模块文件中,哪些文件与写QQ的文件不同?这取决于硬编码的模块结构,但这没关系 如果QQ不可能做到这一点,但任何人都知道实现这一点的不同方式,我愿意听取建议。要回答这个问题,了解准报价人是什么很有帮助。从中,准引号是的值 data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
如果QQ不可能做到这一点,但任何人都知道实现这一点的不同方式,我愿意听取建议。要回答这个问题,了解准报价人是什么很有帮助。从中,准引号是的值
data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
quotePat :: String -> Q Pat,
quoteType :: String -> Q Type,
quoteDec :: String -> Q [Dec] }
也就是说,它是从任意字符串到一个或多个ExpQ
、PatQ
、TypeQ
和DecQ
的解析器,它们分别是表达式、模式、类型和声明的模板Haskell表示
使用准引号时,GHC将解析器应用于字符串以创建ExpQ
(或其他类型),然后拼接生成的模板haskell表达式以生成实际值
听起来像是你要做的是分离Quasikote解析和拼接,这样你就可以访问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。这两种方式都差不多。我想如果你能提到你正试图用它实现的目标,那会很有帮助。从技术上讲,TH可以运行任意IO,包括读取和解析正在编译的模块,因此您可以从不同的位置甚至不同的模块中提取内容,但细节取决于您尝试执行的操作。