简体   繁体   English

模板haskell中的数据构造函数

[英]Data constructor in template haskell

I'm trying to create the ring Z/n (like normal arithmetic, but modulo some integer). 我正在尝试创建环Z / n(像普通算术一样,但模数为整数)。 An example instance is Z4: 一个示例实例是Z4:

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

And so on for the ring. 对于戒指等等。 I'd like to be able to quickly generate these things, and I think the way to do it is with template haskell. 我希望能够快速生成这些东西,我认为这样做的方法是使用模板haskell。 Ideally I'd like to just go $(makeZ 4) and have it spit out the code for Z4 like I defined above. 理想情况下,我想去$(makeZ 4)并像上面定义的那样吐出Z4的代码。

I'm having a lot of trouble with this though. 我虽然遇到了很多麻烦。 When I do genData n = [d| data $n = $n Integer] 当我做genData n = [d| data $n = $n Integer] genData n = [d| data $n = $n Integer] I get "parse error in data/newtype declaration". genData n = [d| data $n = $n Integer]我得到“数据/ newtype声明中的解析错误”。 It does work if I don't use variables though: [d| data Z5 = Z5 Integer |] 如果我不使用变量,它确实有效: [d| data Z5 = Z5 Integer |] [d| data Z5 = Z5 Integer |] , which must mean that I'm doing something weird with the variables. [d| data Z5 = Z5 Integer |] ,这必然意味着我正在做一些奇怪的变量。 I'm not sure what though; 我不确定是什么; I tried constructing them via newName and that didn't seem to work either. 我尝试通过newName构建它们,但似乎也没有用。

Can anyone help me with what's going on here? 任何人都可以帮我解决这里发生的事情吗?

The Template Haskell documentation lists the things you are allowed to splice. Template Haskell文档列出了允许拼接的内容。

A splice can occur in place of 可以用拼接代替

  • an expression; 一种表达; the spliced expression must have type Q Exp 拼接表达式必须具有类型Q Exp
  • an type; 一种类型; the spliced expression must have type Q Typ 拼接表达式必须具有Q Typ类型
  • a list of top-level declarations; 顶级声明列表; the spliced expression must have type Q [Dec] 拼接表达式必须有Q [Dec]Q [Dec]

In both occurrences of $n , however, you're trying to splice a name . 但是,在两次出现的$n中,您都试图拼接一个名称

This means you can't do this using quotations and splices. 这意味着您无法使用引号和拼接来完成此操作。 You'll have to build declaration using the various combinators available in the Language.Haskell.TH module. 您必须使用Language.Haskell.TH模块中提供的各种组合器构建声明。

I think this should be equivalent to what you're trying to do. 我认为这应该等同于你想要做的事情。

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

Yep, it's a bit ugly, but there you go. 是的,它有点难看,但你去了。 To use this, call it with a fresh name, eg 要使用它,请使用新名称调用它,例如

$(genData (mkName "Z5"))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM