【问题标题】:Template Haskell: Stage Error模板 Haskell:阶段错误
【发布时间】:2014-07-23 00:38:44
【问题描述】:

我试图了解 Quasi Quoter 如何生成 TH 结构。所以我试图将Template Meta-programming for Haskell 中的第一个示例从引用格式转换为类型。

gen :: [Format] -> ExpQ -> ExpQ
gen []       x = x
gen (D:xs)   x = [| \n -> $(gen xs [| $x ++ show n |]) |]
gen (S:xs)   x = [| \s -> $(gen xs [| $x ++ s |]) |]
gen (L s:xs) x = gen xs [| $x ++ $(THS.lift s) |]

gen (D:xs) x 将转换为

gen (D:xs)  x = lamE [varP $ mkName "n"]
                    (appE (appE (varE 'gen) (varE 'xs))
                        (uInfixE (x) (varE '(Prelude.++))
                            (appE (varE 'Prelude.show) (varE $ mkName "n"))))

但是,此片段不会编译对 'xs 的引用。

GHC 吐出以下错误:

src/Print/Default.hs:28:51:
    Stage error: the non-top-level quoted name 'xs
    must be used at the same stage at which is is bound
    In the Template Haskell quotation 'xs
    In the first argument of `varE', namely 'xs
    In the second argument of `appE', namely `(varE 'xs)'

是否有其他方式需要引用函数参数的名称,以便 Template Haskell 能够使用它?

【问题讨论】:

  • 转换不正确。请注意,在第一个版本中,引用的本地绑定名称也被拼接回。因此,如果x 是本地绑定的,则不能有$x,但可以有[| ... $x ... |]。在第二个版本中,您还没有这样做,这样做没有意义,因为 lamE [varP ..] 需要 ExpQ 但拼接内部的 \n -> 需要 String

标签: haskell template-haskell


【解决方案1】:

user2407038 是正确的,翻译已关闭。这是一个更正确的翻译:

    gen (D:xs)   x = lamE [varP (mkName "n")] $
                        gen xs $
                              varE '(++)
                                    `appE` x
                                    `appE` (varE 'show `appE` varE (mkName "n"))

您没有在此处引用 xsgen 的名称:您只是递归调用该函数以生成更多 AST。这使一切都保持在同一个阶段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-22
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 2018-02-03
    相关资源
    最近更新 更多