代码之家  ›  专栏  ›  技术社区  ›  jcristovao

准引号是否可以“使用”在被调用的同一文件中定义的变量?

  •  1
  • jcristovao  · 技术社区  · 11 年前

    所以,我开始尝试使用准引号和模板haskell。

    我想修改现有的(大的)准引号代码,同时使用在“调用”处定义的变量的实际值。用一个简单的例子来说明:

    主要.hs

    {-# LANGUAGE QuasiQuotes #-}
    {-# LANGUAGE TemplateHaskell #-}
    
    import Language.Haskell.TH
    import Exp02
    
    x = "cde"
    
    main = do
      putStrLn [str|$x|]
    

    过期02.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”,但这不是我想要的。我的理解是,拼接后得到的主要代码是: putStrLn x 。我想要的是生成 putStrLn cde (我知道这不是有效的haskell代码,但这只是为了表达我的观点)。

    因此,换句话说,我不想“创建对变量的引用” x 在主文件中,我想在 xpto 准引号。

    我猜这可能是不可能的,因为这意味着在 main.hs Exp02.hs 从而面临TH阶段的限制。这是正确的吗,或者有没有办法使用x 价值 内部 xpto公司 密码

    谢谢

    1 回复  |  直到 11 年前
        1
  •  6
  •   Community Grant Miller    4 年前

    不,你现在想做的事情是不可能的。来自 template haskell docs :

    如果函数是从另一个模块导入的,而该模块不是包含当前正在编译的模块的相互递归模块组的一部分,则只能在编译时运行该函数。此外,通过从要运行拼接的模块导入非SOURCE,必须可以访问相互递归组的所有模块。

    例如,在编译模块A时,如果B不导入A(直接或间接),则只能运行从B导入的Template Haskell函数。原因应该很清楚:要运行B,我们必须编译并运行A,但我们目前正在对A进行类型检查。

    您正试图运行函数(或更严格地说是值) x 在编译时与 x 被定义,这是明确表示不允许的。