Haskell 带参数的拟群

Haskell 带参数的拟群,haskell,template-haskell,Haskell,Template Haskell,我想用Haskell写一篇引文。name参数需要传递到gen函数中才能生成声明 quote :: String -> QuasiQuoter quote name = QuasiQuoter { quoteExp = undefined, quotePat = undefined, quoteType = undefined, quoteDec = \jsonStr -> gen name (getValue str)

我想用Haskell写一篇引文。name参数需要传递到gen函数中才能生成声明

quote ::  String -> QuasiQuoter
quote name = QuasiQuoter {
       quoteExp = undefined,
       quotePat = undefined,
       quoteType = undefined,
       quoteDec = \jsonStr -> gen name (getValue str)
     }
但是,我似乎不能这样引用

[quote "Hello"| from x to y |]
由于Haskell不允许quote声明和Quotes位于同一个文件中,这很烦人,我该如何将参数从外部传递到Quotes中?

您有两个选项:

  • 切换到使用拼接
    $(…)
  • 将参数编码为输入字符串中的准引号
  • 使用拼接语法,您的示例如下所示:

    quote :: String -> String -> Q [Dec]
    quote name jsonStr = gen name (getValue jsonStr)
    
    调用它看起来像:
    $(从x到y引用“Hello”)

    为了演示选项2,这里有一个简单的引号,它用一个字符围绕一个文字字符串:

    import Language.Haskell.TH (litE, stringL)
    import Language.Haskell.TH.Quote
    
    surround :: QuasiQuoter
    surround = QuasiQuoter
      { quoteExp  = litE . stringL . (\(c:s) -> [c] ++ s ++ [c])
      , quotePat  = undefined
      , quoteType = undefined
      , quoteDec  = undefined
      }
    
    -- in another file:
    main = print [surround|_some text|] -- prints "_some text_"
    
    输入字符串的第一个字符被解释为要使用的括号字符。实际上,我们已经将
    Char
    参数传递给了
    Char->quasikoter
    类型的函数

    对于更复杂的参数或多个参数,您必须创建自己的语法和解析器来解码它们

    更新:下面是一个稍微复杂的示例,其中调用
    [foo | var xyz |]
    var
    视为变量名称,将
    xyz
    视为文本字符串:

    -- [foo| var xyz|]   is translated to:   var ++ "xyz"
    
    foo :: QuasiQuoter
    foo = QuasiQuoter
      { quoteExp  = go
      , quotePat  = undefined
      , quoteType = undefined
      , quoteDec  = undefined
      }
      where go str = infixE (Just $ varE (mkName var))
                            (varE $ mkName "++")
                            (Just $ litE (stringL arg1))
              where (var:arg1:_) = words str