I was using a return type in a function (using package haskell-src-exts
):
import Language.Haskell.Exts.Syntax (Exp(..))
import Language.Haskell.Exts.SrcLoc (SrcSpanInfo(..))
:k Exp SrcSpanInfo
Exp SrcSpanInfo :: *
That's a type. So far so good.
But now I wanted to type it better:
:set -XDataKinds
> :k 'List
'List :: l -> [Exp l] -> Exp l
So, this thing wants some more stuff. Fine, I can do that.
> :k 'List SrcSpanInfo
'List SrcSpanInfo :: [Exp *] -> Exp *
One step off. Okay.
> :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]’
At this point, I'm feeling quite confused. To me it feels like what I gave it was definitely pretty much what it asked for. What exactly does it mean?
From the comments, it suddenly occurred to me that you're probably not actually looking for the lifted types (i.e. kinds), but rather for regular types.
From the comments (specifically: "...desired kind *...") it seems like you're just looking to construct a value of type Exp SrcSpanInfo
(and indeed, these types are not actually intended for kind-level usage).
To do that, just apply parameters to the constructor:
> span = noInfoSpan $ mkSrcSpan noLoc noLoc
> :t span
span :: SrcSpanInfo
> list = List span []
> :t list
list :: Exp SrcSpanInfo
Original answer
The expression [Exp SrcSpanInfo]
does not denote "a type-level list of types with a single element Exp SrcSpanInfo
", but rather denotes "a single type that is a list of elements of type Exp SrcSpanInfo
", similar to [Int]
or [String]
.
The compiler has no way of distinguishing the former from the latter, so it defaults to the older, more standard interpretation.
In order to make it see a type-level list, it must be quoted with a single quote, just like you did with 'List
.
Further, Exp
is a type, but when used in a kind signature, it's elevated to a kind. In order to construct a type of kind Exp *
, you have to use one of its constructors. I will use the List
constructor, because it was the easiest to instantiate:
> :k 'List SrcSpanInfo '[ 'List SrcSpanInfo '[] ]