jcr*_*vao 1 haskell template-haskell
所以,我开始尝试quasiquotation和模板haskell.
我想修改一个现有的(大)准规则代码,同时使用在"被调用"的地方定义的变量的实际值.举一个简单的例子说明:
main.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Exp02
x = "cde"
main = do
putStrLn [str|$x|]
Run Code Online (Sandbox Code Playgroud)
Exp02.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Exp02 where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote
xpto :: String -> ExpQ
xpto [] = stringE []
xpto ('$':rest) = varE (mkName rest)
xpto str = stringE str
str = QuasiQuoter
{ quoteExp = xpto
, quotePat = fail $ "patterns"
, quoteType= fail $ "types"
, quoteDec = fail $ "declarations"
}
Run Code Online (Sandbox Code Playgroud)
虽然这编译并打印出"cde",但这不是我想要的.我的理解是拼接后的主要代码是:putStrLn x.我想要的是生成putStrLn cde(我知道这不是有效的haskell代码,但它只是代表我的观点).
因此,换句话说,我不想' x在主文件中创建对变量的引用',我想在xptoquasiquoter代码中实际使用它的值.
我猜这可能是不可能的,因为它意味着main.hs和之间的循环引用Exp02.hs,因此面临TH阶段的限制.这是正确的,还是有办法在代码中使用x 值xpto?
谢谢!
不,你想要做的事情目前是不可能的.从模板haskell文档:
如果从另一个模块导入函数,则只能在编译时运行函数,该模块不是包含当前正在编译的模块的相互递归的模块组的一部分.此外,必须通过从要运行拼接的模块的非SOURCE导入来访问互相递归组的所有模块.
例如,在编译模块A时,如果B不直接或间接导入A,则只能运行从B导入的模板Haskell函数.原因应该是明确的:运行B我们必须编译并运行A,但我们目前正在进行类型检查A.
您正尝试x在编译时在x定义的同一模块中运行该函数(或更严格的值),这明确表示不允许.