【问题标题】:Data constructor in template haskell模板haskell中的数据构造函数
【发布时间】:2011-09-27 22:36:46
【问题描述】:

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

谁能帮我看看这里发生了什么?

【问题讨论】:

  • 我不是模板 Haskell 向导,但我敢打赌那些想要查看您的模板 Haskell 代码的人。

标签: haskell template-haskell


【解决方案1】:

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"))

【讨论】:

  • 你能举个例子吗?我稍微修改了你的内容,只是将$(genData "Foo") 作为顶级代码放入我的代码中,但如果我在 ghci 中执行:i Foo,它什么也找不到。
  • @Xodarap:使用mkName 从String 生成Name。我添加了一个例子。我猜你可能使用了newName,它在最后添加了一些东西以确保名称是唯一的,所以:info 不会显示它。不过,您应该可以使用:browse 看到它。
  • 谢谢!这正是我的问题。
猜你喜欢
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 2011-05-24
  • 2017-08-04
  • 1970-01-01
  • 2019-03-14
  • 2013-08-14
相关资源
最近更新 更多