【问题标题】:Couldn't match kind `*' against `#'无法将种类 `*' 与 `#' 匹配
【发布时间】:2013-06-06 17:42:37
【问题描述】:

这到底是怎么回事:

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

我在 GHCi 中使用 TemplateHaskell (ghci -XTemplateHaskell) 尝试以下操作

$(reify ''Show >>= dataToExpQ (const Nothing))

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

我的目标如下:

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

我真的不明白那个错误信息,'#'到底是什么?如果有#,是否还有# -> #* -> #?它是否与种类相关,就像种类与类型相关(尽管我不知道那可能是什么)?


好的,所以我现在明白 GHC 有一个种类的层次结构,而 `#' 是一种特殊的未装箱类型。一切都很好,但是为什么会弹出这个错误?也许未装箱的类型不能很好地与泛型配合使用?

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

经过进一步调查,我认为 Names 提出了问题,有没有办法在 dataToExpQ 中规避它们?无论如何如何使用该参数?

【问题讨论】:

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


【解决方案1】:

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

Data NameFlavor 实例上有一条 Haddock 注释,它引发了一些危险信号。如果您点击源代码,您会看到 gfoldl 定义本质上将未装箱的整数视为整数。 (实际上没有太多其他选择......)这最终会导致您看到的错误,因为 dataToExpQ - 已被欺骗性 Data NameFlavour 实例欺骗 - 构建了一个 Exp 术语,当 NameU 实际期望时将 NameU 应用于 (Int :: *)一个(未装箱)(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 时,您也在具体化范围内的每个 Show 实例。

  • 其中有很多——这会产生一个相当大的语法术语。

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

HTH。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-19
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多