如何显式调用 haskell 语法的准引号?

How to call the quasiquoter for haskell syntax explicitly?

我正在 HaTeX 上构建一个 eDSL。我面临的问题是我想在我的 LaTeX 文档中显示 Haskell 表达式,并且我想使用相同的 Haskell 表达式来帮助生成文档。

显而易见的答案是复制并粘贴表达式,使其同时显示为引用和实时。我想避免这种情况,因为表达式可能会发生变化。

我想象的是一个准引用器,它既拼接其内容,又输出代表它的字符串。

例如,我想输入以下内容:

document = do
    title "this is an example document"
    paragraph "This is normal text. We will now show the Haskell code that generates a table"
    [quoted| makeTable ["heading1","heading2"] ["cell1","cell2"] |]

我想将准报价扩展为:

document = do
    title "this is an example document"
    paragraph "This is normal text. We will now show the Haskell code that generates a table"
    makeTable ["heading1","heading2"] ["cell1","cell2"]
    listing Haskell "makeTable [\"heading1\",\"heading2\"] [\"cell1\",\"cell2\"]"

为此,我需要写一个QuasiQuoter:

quoted :: QuasiQuoter
quoted = QuasiQuoter
     { quoteExp = \str -> [e| $(_ str) >> listing Haskell $(lift str) |] }

我不确定用什么替换 $(_ str) 中的洞。我需要用 Haskell 表达式准引号替换它,但我不确定如何调用它。如果 ee :: QuasiQuoter 我可以用 $(quoteExp e str) 填补这个洞,但不幸的是它不起作用。我应该用什么填充它?

简答:没有简单的方法。 is still was unanswered for a reason. String -> Q Exp for Haskell is tough. The best way is probably through haskell-src-meta which provides parsers which return Template Haskell AST. In particular the Language.Haskell.Meta.Parse 模块给我们 parseExp :: String -> Either String Exp.

import Language.Haskell.Meta.Parse (parseExp)

quoted :: QuasiQuoter
quoted = QuasiQuoter
     { quoteExp = \str ->
         case parseExp str of
           Left msg -> fail "Could not parse expression."
           Right exp -> [e| $(pure exp) >> listing Haskell $(liftString str) |] }