2011-09-27 61 views
11

我正在试图创建Z/n环(就像正常的算术,但是取模一些整数)。一个示例是Z4:模板haskell中的数据构造函数

instance Additive.C Z4 where 
    zero = Z4 0 
    (Z4 x) + (Z4 y) = Z4 $ (x + y) `mod` 4 

等等。我希望能够快速生成这些东西,而且我认为使用模板haskell的方法就是这样。理想情况下,我只想去$(makeZ 4),并让它像我上面定义的Z4一样代码。

虽然我有很多麻烦。当我做genData n = [d| data $n = $n Integer]时,我得到“数据/新类型声明中的解析错误”。如果我不使用变量,它确实有效:[d| data Z5 = Z5 Integer |],这意味着我对变量做了一些奇怪的事情。我不确定是什么;我试图通过newName构建它们,但似乎也没有工作。

任何人都可以帮助我在这里发生了什么?

+0

我不是一个模板哈斯克尔向导,但我打赌谁是希望看到你的模板Haskell代码的人。 –

回答

13

Template Haskell documentation列出了允许拼接的东西。

剪接可发生在取代

  • 的表达;拼接表达式必须具有类型Q Exp
  • 类型;拼接表达式必须具有类型Q Typ
  • 顶级声明的列表;拼接表达式类型必须Q [Dec]

$n两次出现,但是,你要拼接一个

这意味着你不能使用报价和拼接来做到这一点。您必须使用Language.Haskell.TH模块中提供的各种组合器建立声明。

我认为这应该相当于你想要做的。

genData :: Name -> Q [Dec] 
genData n = fmap (:[]) $ dataD (cxt []) n [] 
          [normalC n [strictType notStrict [t| Integer |]]] [] 

是的,这有点丑,但你去。要使用它,请用新名称(例如,

$(genData (mkName "Z5")) 
+0

你能举一个例子吗?我稍微修改了一下,只是把'$(genData“Foo”)'作为顶级代码投入我的代码中,但是如果我在ghci中执行':i Foo',它什么也找不到。 – Xodarap

+1

@Xodarap:使用'mkName'从'String'创建'Name'。我已经添加了一个例子。我想你可能已经使用过'newName',它在最后添加了一些东西以确保名称是唯一的,所以':info'不会显示它。不过,您应该可以使用':browse'来查看它。 – hammar

+0

谢谢!这完全是我的问题。 – Xodarap