派生 Show 的模板 Haskell 数据声明

发布于 2024-12-24 15:50:38 字数 569 浏览 4 评论 0原文

以下内容无法编译:

import Language.Haskell.TH
makeAlpha n = [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]

我根本无法弄清楚错误的含义:

Can't derive instances where the instance context mentions
type variables that are not data type parameters
  Offending constraint: Show t_d
When deriving the instance for (Show Alpha)
In the Template Haskell quotation
  [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
In the expression:
  [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]

是否可以像这样进行推导?

The following doesn't compile:

import Language.Haskell.TH
makeAlpha n = [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]

I can't make out what the error means at all:

Can't derive instances where the instance context mentions
type variables that are not data type parameters
  Offending constraint: Show t_d
When deriving the instance for (Show Alpha)
In the Template Haskell quotation
  [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
In the expression:
  [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]

Is it possible to do derivations like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑着哭最痛 2024-12-31 15:50:38

出现此问题的原因是 TH 引号在编译时进行了类型检查,并用变量替换了拼接。这通常是一个好主意,因为它允许在运行拼接之前检测到多种问题,但在某些情况下,这可能会使编译器错误地拒绝将生成有效代码的拼接。

在这种情况下,这意味着编译器尝试检查此代码:

data Alpha = Alpha t deriving (Show, Read)

这不起作用,因为派生的 ShowRead 实例需要使用 Show 和 Readt,但由于 t 不是 Alpha 的类型参数,因此无法添加必要的限制。当然,当这个拼接运行时,t被替换为具体类型,因此适当的实例将可用而无需任何约束,因此这是编译器正在执行的情况之一过于谨慎。

解决方法是不使用引用,而是使用 TH 组合器,该组合器不受这些额外检查的约束。虽然很混乱,但很有效:

makeAlpha n = sequence [dataD (cxt []) alpha []
                [normalC alpha [strictType notStrict (conT n)]] [''Show, ''Read]]
  where alpha = mkName "Alpha"

一些讨论关于放松对报价的检查,但是对于现在你只需要处理它。

This problem arises because TH quotes are type checked when they are compiled, with splices replaced by variables. This is usually a good idea, because it allows many kinds of problems to be detected before the splice is run, but in some cases this can make the compiler wrongfully reject a splice that would generate valid code.

In this case, this means that the compiler tries to check this code:

data Alpha = Alpha t deriving (Show, Read)

This doesn't work because the derived Show and Read instances need to use Show and Read for t, but since t is not a type parameter of Alpha, it cannot add the necessary constraints. Of course, when this splice is run, t is replaced by a concrete type, so the appropriate instances will be available without the need for any constraints, so this is one of the cases where the compiler is being over-cautious.

The workaround is to not use quoting, but instead use TH combinators, which are not subject to these extra checks. It's messy, but it works:

makeAlpha n = sequence [dataD (cxt []) alpha []
                [normalC alpha [strictType notStrict (conT n)]] [''Show, ''Read]]
  where alpha = mkName "Alpha"

There has been some talk about relaxing the checks done on quotes, but for now you'll just have to deal with it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文