简体   繁体   中英

using list types with Haskell's -XDataKinds

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 (ie 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 '[] ]

[a] is the type of lists. To construct a (promoted) list, write '[a] :

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

Applying 'List to a type, such as SrcSpanInfo , is probably not what you want either (hopefully my example applying it also to an Int tells that something is off).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM