2014-10-10 95 views
12

我正在使用Data.Typeable,特别是我希望能够生成正确类型的特定种类(如*)。我快到的问题是,TypeRep允许我们做如下(以GHC与7.8版本的工作):是否有可能在Haskell中获得类型构造函数的种类?

let maybeType = typeRep (Proxy :: Proxy Maybe) 
let maybeCon = fst (splitTyConApp maybeType) 
let badType = mkTyConApp maybeCon [maybeType] 

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

> :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) 

我不是在寻找在类型级别执行这一点,但我希望能够写一个程序,它是足够聪明,避免在运行时构建这样的类型。我可以使用TypeRep的数据级别来执行此操作。理想情况下,我会像

data KindRep = Star | KFun KindRep KindRep 

,并有一个函数kindOfkindOf Int = Star(大概真的kindOf (Proxy :: Proxy Int) = Star)和kindOf Maybe = KFun Star Star,这样我就可以“种核对”我TypeRep值。

我想我可以用像Typeable这样的多色类型类型手动执行此操作,但我宁愿不必为所有内容编写自己的实例。我还希望不要恢复到GHC 7.6,并使用不同类型的Typeable类型有单独的类型类的事实。我接受从GHC获取这些信息的方法。

+0

'typeOf1'和'Typeable1'(和朋友)仍然从'Data.Typeable'输出......它们在7.8中可用。 – 2014-10-10 05:58:31

回答

12

我们可以得到一种类型,但是我们需要在GHC上抛出大量语言扩展来做到这一点,包括(在这种情况下)超过可疑的UndecidableInstancesAllowAmbiguousTypes

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

import Data.Proxy 

使用你定义一个KindRep

data KindRep = Star | KFun KindRep KindRep 

我们定义类的Kindable东西,其种类可确定

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

这样做的第一个实例是容易的,那种一切*Kindable

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

获得更高类型的类型很难。我们会试着说,如果我们能够找到它的论点的种类和将它用于论证的结果的种类,我们可以找出它的种类。不幸的是,由于它没有争论,我们不知道它的论点是什么类型;这就是为什么我们需要AllowAmbiguousTypes

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)) 

只是不要试图确定的那种类型polykinded像Proxy

kindOf (Proxy :: Proxy Proxy) 

所幸导致编译器错误只在有限的时间内完成。

+0

仅供参考,我遇到的大多数Haskell高手都认为'UndecidableInstances'是一个合理的东西。我想'AllowAmbiguousTypes'可能会在阴暗的一面 - 这是否会使推论有点片面? – dfeuer 2014-10-10 07:34:35

相关问题