派生 Show 的模板 Haskell 数据声明
以下内容无法编译:
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
出现此问题的原因是 TH 引号在编译时进行了类型检查,并用变量替换了拼接。这通常是一个好主意,因为它允许在运行拼接之前检测到多种问题,但在某些情况下,这可能会使编译器错误地拒绝将生成有效代码的拼接。
在这种情况下,这意味着编译器尝试检查此代码:
这不起作用,因为派生的
Show
和Read
实例需要使用Show 和
Read
为t
,但由于t
不是Alpha
的类型参数,因此无法添加必要的限制。当然,当这个拼接运行时,t
被替换为具体类型,因此适当的实例将可用而无需任何约束,因此这是编译器正在执行的情况之一过于谨慎。解决方法是不使用引用,而是使用 TH 组合器,该组合器不受这些额外检查的约束。虽然很混乱,但很有效:
一些讨论关于放松对报价的检查,但是对于现在你只需要处理它。
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:
This doesn't work because the derived
Show
andRead
instances need to useShow
andRead
fort
, but sincet
is not a type parameter ofAlpha
, 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:
There has been some talk about relaxing the checks done on quotes, but for now you'll just have to deal with it.