如何在反引号中不仅允许嵌入值而是嵌入任意haskell表达式

时间:2013-10-19 13:13:08

标签: haskell template-haskell quotations

最近,我学会了如何在下面的代码中实现具有反引号功能的quasiquoter,例如printfQ

main = do
  let itemName = "apple"
      price = 1.29 
  [printfQ| The price of #{itemName} is #{price}. |]

quasiquote的成分字符串将传递给quoteExp printfQ :: String -> ExpQ。我们所做的就是解析给定的String,找到要嵌入的名称"itemName""price",为每个名称应用varE . mkName,然后构建ExpQ

现在假设我想扩展此printfQ以允许表达式嵌入,如下所示:

[printfQ| The price of #{itemNames !! i} is #{price + taxOf price}. |]

我可以编写检测两个字符串"itemNames !! i""price + taxOf price"的解析器。但后来我需要一个更强版本的varE . mkName,类型为String -> ExpQ的函数,将这些字符串转换为ExpQ,将它们解释为引用printfQ命名空间的表达式

我的问题:是否有任何库函数可以将此字符串转换为AST转换?有没有一些简单的方法可以做到这一点,还是我需要编写一个完整的Haskell解析器?

1 个答案:

答案 0 :(得分:4)

洗完澡后,我有一个好主意:

  

嘿,如果我需要一个完整的Haskell解析器,为什么不使用现有的?

经过几行搜索,我找到了答案:parseExp来自 http://hackage.haskell.org/package/haskell-src-meta-0.6.0.4/docs/Language-Haskell-Meta-Parse.html#v:parseExp

我为此写了一个自包含的例子:

https://github.com/nushio3/practice/tree/master/template-haskell/embed-expr