有可能在Haskell中获得类型构造函数的类型吗?

有可能在Haskell中获得类型构造函数的类型吗?,haskell,type-kinds,Haskell,Type Kinds,我正在处理Data.Typeable,尤其是我希望能够生成特定类型的正确类型(比如*)。我遇到的问题是TypeRep允许我们执行以下操作(使用GHC 7.8中的版本): 这里的badType在某种意义上是类型Maybe-Maybe的表示,它不是任何类型的有效类型: > :k Maybe (Maybe) <interactive>:1:8: Expecting one more argument to ‘Maybe’ The first argument of

我正在处理Data.Typeable,尤其是我希望能够生成特定类型的正确类型(比如
*
)。我遇到的问题是TypeRep允许我们执行以下操作(使用GHC 7.8中的版本):

这里的
badType
在某种意义上是类型Maybe-Maybe的表示,它不是任何类型的有效类型:

> :k Maybe (Maybe)

<interactive>:1:8:
    Expecting one more argument to ‘Maybe’
    The first argument of ‘Maybe’ should have kind ‘*’,
      but ‘Maybe’ has kind ‘* -> *’
    In a type in a GHCi command: Maybe (Maybe)
并且有一个函数
kindOf
kindOf Int=Star
(可能真的
kindOf(Proxy::Proxy Int)=Star
)和
kindOf Maybe=KFun Star
,这样我就可以“检查”我的TypeRep值


我想我可以用一个类似于
Typeable
的多类typeclass手动完成这项工作,但我更愿意不必为所有内容编写自己的实例。我也不希望回到GHC7.6,而是使用这样一个事实:对于不同类型的可键入类型,有单独的类型类。我对从GHC获取此信息的方法持开放态度。

我们可以获得类型的类型,但我们需要在GHC中抛出大量的语言扩展来实现这一点,包括(在本例中)超过可疑的
不可判定实例
AllowAmbiguousTypes

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

import Data.Proxy
instance (Kindable a, Kindable (f a)) => Kindable f where
    kindOf _ = KFun (kindOf (Proxy :: Proxy a)) (kindOf (Proxy :: Proxy (f a)))
将您的定义用于
KindRep

data KindRep = Star | KFun KindRep KindRep
我们定义了
Kindable
可以确定其种类的事物的类别

class Kindable x where
    kindOf :: p x -> KindRep
第一个例子很简单,任何类型的
*
都是
Kindable

instance Kindable (a :: *) where
    kindOf _ = Star
要得到更高级的类型是很难的。我们试着说,如果我们能找到它的论点的类型,以及把它应用到论点的结果,我们就能找出它的类型。不幸的是,因为它没有参数,我们不知道它的参数是什么类型;这就是为什么我们需要
AllowAmbiguousTypes

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

import Data.Proxy
instance (Kindable a, Kindable (f a)) => Kindable f where
    kindOf _ = KFun (kindOf (Proxy :: Proxy a)) (kindOf (Proxy :: Proxy (f a)))
结合起来,这些定义允许我们写下

 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))
只是不要像
Proxy

 kindOf (Proxy :: Proxy Proxy)

幸运的是,这只会在有限的时间内导致编译器错误。

typeOf1
Typeable1
(和朋友)仍然从
数据导出。Typeable
。。。它们在7.8FYI中可用,我所遇到的大多数Haskell硕士认为 unDeIDable实例是一个合理的事情。我想
AllowAmbiguousTypes
可能有点阴暗,但这是否会让推断有点不可靠?