问题 模板haskell中的数据构造函数


我正在尝试创建环Z / n(像普通算术一样,但模数为整数)。一个示例实例是Z4:

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] 我得到“数据/ newtype声明中的解析错误”。如果我不使用变量,它确实有效: [d| data Z5 = Z5 Integer |],这必然意味着我正在做一些奇怪的变量。我不确定是什么;我尝试通过newName构建它们,但似乎也没有用。

任何人都可以帮我解决这里发生的事情吗?


11019
2017-09-27 01:00


起源

我不是一个模板Haskell向导,但我打赌那些想要看到你的模板Haskell代码的人。 - Daniel Wagner


答案:


模板Haskell文档 列出允许拼接的东西。

可以用拼接代替

  • 一种表达;拼接表达式必须具有类型 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"))

13
2017-09-27 01:35



你能举一个使用它的例子吗?我修改了你的东西,然后扔了 $(genData "Foo") 作为我的代码的顶级,但如果我这样做 :i Foo 在ghci它没有找到任何东西。 - Xodarap
@Xodarap:使用 mkName 做一个 Name 从一个 String。我添加了一个例子。我想你可能已经习惯了 newName,最后添加一些东西以确保名称是唯一的,所以 :info 不会表现出来。你应该能够看到它 :browse但是。 - hammar
谢谢!这完全是我的问题。 - Xodarap