Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Haskell中编译期间在不同的位置包含代码?_Haskell_Abstract Syntax Tree_Template Haskell - Fatal编程技术网

如何在Haskell中编译期间在不同的位置包含代码?

如何在Haskell中编译期间在不同的位置包含代码?,haskell,abstract-syntax-tree,template-haskell,Haskell,Abstract Syntax Tree,Template Haskell,准引号允许在编译期间生成AST代码,但它会在编写准引号的位置插入生成的代码。是否可以以任何方式将编译时生成的代码插入其他地方?例如,在特定的模块文件中,哪些文件与写QQ的文件不同?这取决于硬编码的模块结构,但这没关系 如果QQ不可能做到这一点,但任何人都知道实现这一点的不同方式,我愿意听取建议。要回答这个问题,了解准报价人是什么很有帮助。从中,准引号是的值 data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,

准引号允许在编译期间生成AST代码,但它会在编写准引号的位置插入生成的代码。是否可以以任何方式将编译时生成的代码插入其他地方?例如,在特定的模块文件中,哪些文件与写QQ的文件不同?这取决于硬编码的模块结构,但这没关系


如果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,包括读取和解析正在编译的模块,因此您可以从不同的位置甚至不同的模块中提取内容,但细节取决于您尝试执行的操作。