将列表类型与 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 '[] ]
我在函数中使用 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 '[] ]