我想在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不允许引用声明和引用在同一个令人烦恼的文件中,我该怎样做才能将参数从外部传递到引用中?
答案 0 :(得分:6)
您有两种选择:
$(...)
,使用拼接语法,您的示例如下所示:
quote :: String -> String -> Q [Dec]
quote name jsonStr = gen name (getValue jsonStr)
并调用它看起来像:$(quote "Hello" "from x to y")
为了演示选项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 -> QuasiQuoter
的函数。
对于更复杂的参数或多个参数,您必须创建自己的语法和解析器来解码它们。
更新:这是一个稍微复杂的示例,其中调用[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