无法与'#'匹配`*'

时间:2013-06-10 23:43:40

标签: haskell ghc generic-programming template-haskell type-kinds

这里到底发生了什么:

"Couldn't match kind `*' against `#'"

我使用TemplateHaskell(ghci -XTemplateHaskell

在GHCi中尝试以下操作
$(reify ''Show >>= dataToExpQ (const Nothing))

我希望得到一个Exp(它有一个Show的实例)。我这样做是为了在应用程序中插入有关haskell类型的信息,使其可用作实际数据,而不是字符串。

我的目标如下:

info :: Info
info = $(reify ''Show >>= dataToExpQ (const Nothing))

我真的不明白这个错误信息,反正是什么'#'?如果有#,还有# -> #还是* -> #?它是否与类型相关的类型有关(虽然我不知道那可能是什么)?


好的,所以我现在明白GHC有种类的层次结构,而'#'是一种特殊的无盒装类型。一切都很好,但为什么会弹出这个错误?也许未装箱的类型与genercis不相符?

我还不完全确定这对我有意义,因为我会认为未装箱的类型是由编译器执行的优化。我还认为,如果存在数据实例,则需要存在可能包含在数据结构中的所有类型。

经过进一步调查,我认为Names会造成问题,有没有办法在dataToExpQ中绕过它们?无论如何如何使用该论点?

1 个答案:

答案 0 :(得分:4)

你是对的,导致问题的是名字。更具体地说,问题是NameFlavour数据类型在其某些字段中具有未装箱的整数。

Data NameFlavor实例上有一个Haddock注释会引发一些危险信号。如果你点击源代码,你会看到gfoldl定义基本上处理未整数的整数,如整数。 (实际上没有其他选择...)这最终会导致您看到的错误,因为dataToExpQ - 被欺骗性的Data NameFlavour实例欺骗 - 构建一个ExpName,在NameU实际期望的时候将NameU应用于(Int :: *) an(unboxed)(Int#::#)。

所以问题是NameFlavour的Data实例违反了dataToExpQ假定的不变量。但不要担心!这种情况完全在于dataToExpQ采用参数的原因:该参数允许我们为麻烦的类型提供特殊处理。下面,我这样做是为了正确地重新定义具有未装箱整数字段的NameFlavour构造函数。

可能有解决方案,但我不知道它们,所以我卷起了以下内容。由于TH分段限制,它需要一个单独的模块。

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MagicHash #-}

module Stage0 where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax

import GHC.Types (Int(I#))
import GHC.Prim (Int#)

unboxed :: Int# -> Q Exp
unboxed i = litE $ intPrimL $ toInteger $ I# i -- TH does support unboxed literals

nameFlavorToQExp :: NameFlavour -> Maybe (Q Exp)
nameFlavorToQExp n = case n of
  NameU i -> Just [| NameU $(unboxed i) |]
  NameL i -> Just [| NameL $(unboxed i) |]
  _ -> Nothing

然后以下内容为我编译。

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import Language.Haskell.TH.Quote

import Generics.SYB
import Stage0

info :: Info
info = $(reify ''Show >>= dataToExpQ (mkQ Nothing nameFlavorToQExp))

CAVEAT PROGRAMMER我们向后弯曲的未装箱整数对应于GHC内部使用的“唯一”。它们不一定是序列化的。根据您使用生成的Info值的方式,这可能会导致爆炸。

另请注意,在显示“显示”时,您还要为范围内的每个Show实例进行一次。

  • 有很多 - 这会产生一个非常大的语法术语。

  • 正如the documentation所述,这些实例不包含方法定义。

HTH。