将列表类型与 Haskell 的 -XDataKinds 一起使用

using list types with Haskell's -XDataKinds

我在函数中使用 return 类型(使用包 haskell-src-exts):

import Language.Haskell.Exts.Syntax (Exp(..))
import Language.Haskell.Exts.SrcLoc (SrcSpanInfo(..))
:k Exp SrcSpanInfo
Exp SrcSpanInfo :: *

这是一种类型。到目前为止一切顺利。

但现在我想输入得更好:

:set -XDataKinds
> :k 'List
'List :: l -> [Exp l] -> Exp l

所以,这东西需要更多的东西。好吧,我可以。

> :k 'List SrcSpanInfo 
'List SrcSpanInfo :: [Exp *] -> Exp *

退一步。好的

> :k 'List SrcSpanInfo [Exp SrcSpanInfo]

<interactive>:1:19: error:
    • Expected kind ‘[Exp *]’, but ‘[Exp SrcSpanInfo]’ has kind ‘*’
    • In the second argument of ‘ 'List’, namely ‘[Exp SrcSpanInfo]’
      In the type ‘ 'List SrcSpanInfo [Exp SrcSpanInfo]’

在这一点上,我感到很困惑。 对我来说,感觉就像我给它的几乎就是它所要求的。 具体是什么意思?

[a] 是列表的类型。要构建(提升的)列表,请编写 '[a]:

:k 'List SrcSpanInfo '[ 'List Int '[] ]

'List 应用于类型,例如 SrcSpanInfo,可能也不是您想要的(希望我的示例也将其应用于 Int 表明有问题) .

根据评论,我突然想到您实际上可能不是在寻找提升类型(即种类),而是在寻找常规类型。

从评论(特别是:“...desired kind *...”来看,您似乎只是想构造一个 [=12 类型的值=](事实上,这些类型实际上并不是为了种类级别的使用而设计的)。

为此,只需将参数应用于构造函数:

> span = noInfoSpan $ mkSrcSpan noLoc noLoc
> :t span
span :: SrcSpanInfo
> list = List span []
> :t list
list :: Exp SrcSpanInfo

原回答

表达式 [Exp SrcSpanInfo] 不表示“具有单个元素的类型级别列表 Exp SrcSpanInfo”,而是表示“一个单一类型,它是Exp SrcSpanInfo”类型元素的列表,类似于[Int][String]

编译器无法区分前者和后者,因此它默认使用更旧的、更标准的解释。

为了让它看到一个类型级别的列表,它必须用单引号引起来,就像您对 'List 所做的那样。

此外,Exp 是一种类型,但在种类签名中使用时,它被提升为种类。为了构造类型 Exp *,您必须使用 one of its constructors。我将使用 List 构造函数,因为它最容易实例化:

> :k 'List SrcSpanInfo '[ 'List SrcSpanInfo '[] ]