导出Show的模板Haskell数据声明

Ana*_*Ana 8 haskell template-haskell

以下内容无法编译:

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

我无法弄清楚错误意味着什么:

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) |]
Run Code Online (Sandbox Code Playgroud)

有可能做这样的派生吗?

ham*_*mar 7

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

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

data Alpha = Alpha t deriving (Show, Read)
Run Code Online (Sandbox Code Playgroud)

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

解决方法是不使用引用,而是使用TH组合器,这些组合器不受这些额外检查的限制.这很麻烦,但它有效:

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

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