Is it possible to get the Kind of a Type Constructor in Haskell?

我是研究僧i 提交于 2019-12-04 01:04:30

We can get the kind of a type, but we need to throw a whole host of language extensions at GHC to do so, including the (in this case) exceeding questionable UndecidableInstances and AllowAmbiguousTypes.

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}

import Data.Proxy

Using your definition for a KindRep

data KindRep = Star | KFun KindRep KindRep

we define the class of Kindable things whose kind can be determined

class Kindable x where
    kindOf :: p x -> KindRep

The first instance for this is easy, everything of kind * is Kindable:

instance Kindable (a :: *) where
    kindOf _ = Star

Getting the kind of higher-kinded types is hard. We will try to say that if we can find the kind of its argument and the kind of the result of applying it to an argument, we can figure out its kind. Unfortunately, since it doesn't have an argument, we don't know what type its argument will be; this is why we need AllowAmbiguousTypes.

instance (Kindable a, Kindable (f a)) => Kindable f where
    kindOf _ = KFun (kindOf (Proxy :: Proxy a)) (kindOf (Proxy :: Proxy (f a)))

Combined, these definitions allow us to write things like

 kindOf (Proxy :: Proxy Int)    = Star
 kindOf (Proxy :: Proxy Maybe)  = KFun Star Star
 kindOf (Proxy :: Proxy (,))    = KFun Star (KFun Star Star)
 kindOf (Proxy :: Proxy StateT) = KFun Star (KFun (KFun Star Star) (KFun Star Star))

Just don't try to determine the kind of a polykinded type like Proxy

 kindOf (Proxy :: Proxy Proxy)

which fortunately results in a compiler error in only a finite amount of time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!