6

我刚刚开始使用 Template Haskell(我终于有了一个用例,耶!)现在我在认知上陷入了困境。

我想要做的是生成表单的单例数据类型声明

data $V = $V deriving (Eq,Ord)

从名称V开始(希望以大写字符开头!)。明确地说,我正在尝试编写一个declareSingleton类型的函数String -> DecsQ(我应该在这里提到我正在使用 GHC 7.6.1,template-haskell 版本 2.8.0.0),以便拼接

$(declareSingleton "Foo")

相当于

data Foo = Foo deriving (Eq,Ord)

我已经让以下代码工作并做我想做的事,但我对它不是很满意:

declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in sequence [
        dataD (cxt []) n [] [normalC n []] [''Eq,''Ord]
   ]

我希望得到类似以下的工作:

declareSingleton :: String -> Q [Dec]
declareSingleton s = let n = mkName s in 
    [d| data $n = $n deriving (Eq,Ord) |]

我尝试过各种, , ,的组合$s,但无济于事(但并非详尽无遗!) ,所以我不得不假设我对 Template Haskell 工作原理的心智模型过于简单。$v$(conT v)v'v

我是否在这里遗漏了一些明显的东西,我是否以某种基本方式混淆了类型名称和构造函数名称,我可以用declareSingleton一种很好的(r)方式编写吗?

如果是,如何;如果不是,为什么不呢?

(旁注:Haskell 模板 API 变化很快,我为此感到高兴——我希望这个简单的类型最终实现一个具有关联类型族的多参数类型类——但 API 目前正在经历的流失并没有' t 使搜索教程变得容易!TH 在 6.12.1 或 7.2(大多数现有教程的编写时)中的实现方式与现在的工作方式有很大的不同......)

4

2 回答 2

4

模板 Haskell 文档中:

拼接可以代替

  • 一种表达; 拼接后的表达式必须是 Q Exp 类型
  • 一种类型;拼接后的表达式必须是 Q Typ 类型
  • 顶级声明列表;拼接后的表达式必须为 Q [Dec] 类型

因此,例如构造函数名称根本无法在当前版本的 Template Haskell 中拼接。

我认为您可以做很多事情来简化这个用例(除非将整个声明构造为字符串并将其转换为Decvia toDecin haskell-src-meta)。

您可以考虑简单地将声明的不同部分绑定到局部变量。虽然更冗长,但它使代码更易于阅读。

declareSingleton :: String -> Q [Dec]
declareSingleton s = return [DataD context name vars cons derives] where
    context  = []
    name     = mkName s
    vars     = []
    cons     = [NormalC name fields]
    fields   = []
    derives  = [''Eq, ''Ord]
于 2013-03-08T08:37:59.037 回答
0

解析插值字符串而不是构造 AST 的 hack:

makeU1 :: String -> Q [Dec]
makeU1 = makeSingletonDeclaration >>> parseDecs >>> fromRight >>> return

makeSingletonDeclaration :: String -> String
makeSingletonDeclaration name = [qq|data {name} = {name} deriving (Show)|]

在哪里:

parseDecs :: String -> Either String [Dec]

用法:

makeU1 "T"
main = print T

它需要这些软件包:

$ cabal install haskell-src-exts
$ cabal install haskell-src-meta
$ cabal install interpolatedstring-perl6

可运行脚本:

https://github.com/sboosali/haskell/blob/0794eb7a52cf4c658270e49fa4f0d9e53c4b0ebf/TemplateHaskell/Splice.hs

于 2014-11-03T22:51:00.293 回答