8

以下内容无法编译:

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

有可能做这样的推导吗?

4

1 回答 1

7

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

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

data Alpha = Alpha t deriving (Show, Read)

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

解决方法是不使用引用,而是使用不受这些额外检查的 TH 组合子。这很混乱,但它有效:

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

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

于 2011-12-31T18:35:14.527 回答