因此,我开始尝试使用 quasiquotation 和模板 haskell。
我想修改现有的(大)准引用代码,同时使用在“调用”位置定义的变量的实际值。用一个简单的例子来说明:
主文件
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Exp02
x = "cde"
main = do
putStrLn [str|$x|]
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"
}
虽然这会编译并打印出“cde”,但这不是我想要的。我的理解是拼接后main中的结果代码是:putStrLn x
. 我想要的是生成putStrLn cde
(我知道这不是有效的haskell代码,但这只是为了代表我的观点)。
因此,换句话说,我不想“x
在主文件中创建对变量的引用”,我想在xpto
quasiquoter 代码中实际使用它的值。
我猜这可能是不可能的,因为它意味着main.hs
and之间的循环引用Exp02.hs
,因此面临 TH 阶段限制。这是正确的,还是有办法在代码中使用 x值xpto
?
谢谢!