admin管理员组文章数量:1404927
When I wrote
data Y1 f a where
Y1 :: (b -> a) -> f b -> Y1 f a
GHC 9.12.1 infered its kind as Y1 :: (Type -> Type) -> Type -> Type
. But when I gave a kind signature to make f
poly-kinded, GHC accepted it.
type Y1 :: (k -> Type) -> Type -> Type
data Y1 f a where
Y1 :: (b -> a) -> f b -> Y1 f a
But I'm not sure how I can use a kind other than Type
as k
. I need to make either a
or b
not Type
, but a kind of (->)
is Type -> Type -> Type
, and a
and b
have to be Type
.
Can I ask why it can be poly-kinded, and how I can use it?
Also, I found that GHC didn't allow me to make it poly-kinded with ExistentialQuantification
.
data Y2 f a = forall k (b :: k). Y2 (b -> a) (f b)
GHC made this an error.
<interactive>:50:38: error: [GHC-25897]
• Expected a type, but ‘b’ has kind ‘k’
• In the type ‘(b -> a)’
In the definition of data constructor ‘Y2’
In the data declaration for ‘Y2’
This kind of makes sense, but I'm not sure why GHC allowed it with GADT-syntax, but didn't allow it with ExistentialQuantification
.
When I wrote
data Y1 f a where
Y1 :: (b -> a) -> f b -> Y1 f a
GHC 9.12.1 infered its kind as Y1 :: (Type -> Type) -> Type -> Type
. But when I gave a kind signature to make f
poly-kinded, GHC accepted it.
type Y1 :: (k -> Type) -> Type -> Type
data Y1 f a where
Y1 :: (b -> a) -> f b -> Y1 f a
But I'm not sure how I can use a kind other than Type
as k
. I need to make either a
or b
not Type
, but a kind of (->)
is Type -> Type -> Type
, and a
and b
have to be Type
.
Can I ask why it can be poly-kinded, and how I can use it?
Also, I found that GHC didn't allow me to make it poly-kinded with ExistentialQuantification
.
data Y2 f a = forall k (b :: k). Y2 (b -> a) (f b)
GHC made this an error.
<interactive>:50:38: error: [GHC-25897]
• Expected a type, but ‘b’ has kind ‘k’
• In the type ‘(b -> a)’
In the definition of data constructor ‘Y2’
In the data declaration for ‘Y2’
This kind of makes sense, but I'm not sure why GHC allowed it with GADT-syntax, but didn't allow it with ExistentialQuantification
.
2 Answers
Reset to default 6If you enable -fprint-explicit-foralls
and -fprint-explicit-kinds
, you see that the Y1
type constructor has the following kind:
> :k Y1
Y1 :: forall k. (k -> Type) -> Type -> Type
While the Y1
data constructor has the following type:
> :t Y1
Y1 :: forall b a (f :: Type -> Type). (b -> a) -> f b -> Y1 @Type f a
In other words, while the type of the Y1
data constructor forces b
to have kind Type
, nothing prevents you from adding another constructor that returns a Y1 @k f a
for some other kind k
.
One of the things you can do with GADT syntax is to implicitly specialize type variables. For example, you can write
data T a where T :: T Bool
and although the kind of T
makes it look like it can accept any type, in reality you can only ever build T Bool
s. Alternately, you could think of this as having a constraint on the type argument:
data T a where T :: a ~ Bool => T a
This is what's happening to you: the k
from your kind declaration is getting implicitly constrained:
type Y1 :: (k -> Type) -> Type -> Type
data Y1 f a where
Y1 :: {k ~ Type =>} (b -> a) -> f b -> Y1 f a
So you can have any kind k
you want, as long as you want Type
.
本文标签: haskellWhy can an existential type be polykindedStack Overflow
版权声明:本文标题:haskell - Why can an existential type be poly-kinded? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744869203a2629526.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论