2013-09-29 49 views
5

GHC拒絕程序GHC有沒有更深的類型 - 理論原因不能推斷這種類型?

{-# LANGUAGE GADTs #-} 
{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE TypeOperators #-} 
import GHC.TypeLits 

data Foo = Foo 
data Bar = Bar 

data (:::) :: * -> * -> * where 
    (:=) :: sy -> t -> sy ::: t 

data Rec :: [*] -> * where 
    RNil :: Rec '[] 
    (:&) :: (sy ::: ty) -> Rec xs -> Rec ((sy ::: ty) ': xs) 

infix 3 := 
infixr 2 :& 

baz :: Num ty => Rec [Foo ::: String, Bar ::: ty] 
baz = Foo := "foo" :& Bar := 1 :& RNil 

--bang :: (String, Integer) 
bang = case baz of 
     (Foo := a :& Bar := b :& RNil) -> (a, b) 

Rec2.hs:25:44: 
    Couldn't match type ‛t’ with ‛(String, Integer)’ 
     ‛t’ is untouchable 
     inside the constraints (xs1 ~ '[] *) 
     bound by a pattern with constructor 
        RNil :: Rec ('[] *), 
       in a case alternative 
     at Rec2.hs:25:35-38 
     ‛t’ is a rigid type variable bound by 
      the inferred type of bang :: t at Rec2.hs:24:1 
    Expected type: t 
     Actual type: (ty, ty1) 
    Relevant bindings include bang :: t (bound at Rec2.hs:24:1) 
    In the expression: (a, b) 
    In a case alternative: (Foo := a :& Bar := b :& RNil) -> (a, b) 
    In the expression: 
     case baz of { (Foo := a :& Bar := b :& RNil) -> (a, b) } 

,用類型標註它工作正常。所有關於我在網絡上發現的不可觸摸類型變量和GADT的答案都斷言類型推斷是不可能的,或者至少是棘手的,但在這種情況下,似乎很明顯GHC得到了類型(String, Integer),它只是拒絕統一。

+0

如果monomorphize'baz'工作的呢? –

+0

不,它沒有。 – barsoap

回答

4

也許你原來GADT可能是糖的東西,不使用GADTs像下面的(工作):

{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE TypeOperators #-} 
import GHC.TypeLits 

data Foo = Foo 
data Bar = Bar 

data (:::) sy t = (:=) sy t 

data RNil = RNil 
data (:&) a b = a :& b 

type family Rec (xs :: [*]) :: * 
type instance Rec (x ': xs) = x :& Rec xs 
type instance Rec '[] = RNil 

infix 3 := 
infixr 2 :& 

baz :: Num ty => Rec [Foo ::: String, Bar ::: ty] 
baz = Foo := "foo" :& Bar := 1 :& RNil 

bang = case baz of 
     (Foo := a :& Bar := b :& RNil) -> (a, b) 
+0

這是一個*非常*好的建議,我打算玩,看看它是如何與我的其他計劃相互作用的,但它並沒有真正回答我的問題,儘管:) – barsoap

+0

嗯。這樣做的一個結果是,現在「baz」的推斷類型不是一個很好的「Rec」,其元素被列爲類型參數,如在例如。乙烯基,但一個類型級別的列表拉拉斯特,記錄等。這是我絕對想要的,我會犧牲它的模式匹配。這一切都與數據家族很好地協作,但最終可能是我想要的。 – barsoap

+1

那麼這個例子表明你不需要GADT的所有功能來處理你的'數據記錄',但是你仍然在類型推斷方面付出代價......所以也許有一些空間讓GADT有很好的語法同時將類型推斷保持爲良好的普通ADT。 – aavogt