10

我正在玩 Template Haskell。我想创建一个准引用器,它允许我为记录创建默认初始化程序,即类似

[record| data Config = { shouldDoX = True; featureY :: Integer, optionZ = Nothing } |]

应该创建一个函数

defaultConfig = Config { shouldDoX = True, optionZ = Nothing }

基本上它与数据声明的语法相同,由默认值扩展。现在record是一个自定义的 QuasiQuoter,但是我不想在其中解析自己的表达式和类型。理想情况下,我只需要将花括号内的块划分为语句并查找=and ::

[e| ...|]所以我正在寻找一个与使用or引用有效相同的函数[t| ...|]。我在 Hoogle 中搜索了一个函数String -> ExpQ,或者String -> Q Exp没有找到任何东西。

如果我不清楚我在寻找什么:我知道 QuasiQuoters。正如我所提到的:record 一个 QuasiQuoter。现在传递给我的准引用器的字符串包含表达式 (like Node 7 (Node 8 Nil Nil) Nil) 和类型 (like Trueor Maybe (Either A B))。我可以自己解析这些,但我希望有一个函数可以为我完成,就像我将字符串传递到像[e|...|].

所以:我正在寻找一个函数,我可以将表达式作为字符串或类型作为字符串提供,并返回适当的ExpType对象。我相信它必须存在于 Q monad 中,因为它应该根据上下文评估表达式或类型(就像引用一样)。

functionOfMyDreams "Node 7 (Node 8 Nil Nil) Nil" :: Q Exp
4

2 回答 2

4

我认为功能

parseExp :: String -> Either String Exp
parseType :: String -> Either String Type

from haskell-src-metapackage 是你想要的。

http://hackage.haskell.org/package/haskell-src-meta-0.6.0.4/docs/Language-Haskell-Meta-Parse-Careful.html

这是一个quasiquoter的自包含示例haskell-src-meta,它可以使用.

于 2013-10-19T14:38:09.203 回答
1

你有正确的想法,但它会是一个像String -> Q [Dec]

要创建一个 quasiquoter,你必须创建一个QuasiQuoter类型的值,它有四个类型的函数,String -> Q Blah其中 Blah 是你正在拼接的 Template Haskell 类型。

在您的情况下,您只需要定义声明引用者。

quoteRecord :: String -> Q [Dec]
quoteRecord = ...

record :: QuasiQuoter
record = QuasiQuoter (error "record is not a expression quoter")
                     (error "record is not a pattern quoter")
                     (error "record is not a type quoter")
                     quoteRecord

然后您可以在另一个文件中使用您的记录准引用器

[record| ... |]

Haskell wiki上有一个很好的演练

您可能还想查看BNFC-meta,它将从语法中生成一个 quasiquoter。

于 2013-03-27T17:03:53.820 回答