2014-09-20 116 views
7

我不明白,爲什麼下面的代碼不會編譯:類型變量「A0」是不明確的

{-# LANGUAGE GADTs, ScopedTypeVariables #-} 

data A = A 

class C a where 
    c :: a -> Bool 

instance C A where 
    c _ = True 

data D a where 
    D :: C a => D a 

toBool :: D a -> Bool 
toBool D = c (undefined::a) 

以下是錯誤消息:

Could not deduce (C a0) arising from a use of ‘c’ 
from the context (C a) 
    bound by a pattern with constructor 
      D :: forall a. C a => D a, 
      in an equation for ‘toBool’ 
    at test.hs:15:8 
The type variable ‘a0’ is ambiguous 
Note: there is a potential instance available: 
    instance C A -- Defined at test.hs:8:10 
In the expression: c (undefined :: a) 
In an equation for ‘toBool’: toBool D = c (undefined :: a) 

有人能解釋這是怎麼回事上 ?

+5

'ScopedTypeVariables'要求你明確地寫出哪些類型的簽名應該被寫出來:'toBool :: forall a。 D a - > Bool'。 – user2407038 2014-09-20 05:00:17

回答

10

在頂層類型聲明中引入的類型變量與在函數體內引入的類型變量不同。另一種說法是嵌套類型聲明引入了「新鮮」變量。另一種方式說,這是把明確forall在你的代碼中哈斯克爾自動介紹他們,默默:

toBool :: forall a . D a -> Bool 
toBool D = c (undefined :: forall a . a) -- another forall here? 

你真的打算什麼

toBool :: forall a . D a -> Bool 
toBool D = c (undefined :: a) -- capture `a` from prior scope 

而且,你很幸運。事實證明,幾乎每個人都會不時需要這種功能,所以存在一個非常常見的Haskell擴展名爲ScopedTypeVariables。下面的代碼應該編譯

{-# LANGUAGE ScopedTypeVariables #-} 

toBool :: forall a . D a -> Bool 
toBool D = c (undefined :: a) 

注意,以便調用ScopedTypeVariables現在必須手動介紹要特殊對待的forall秒。沒有那個手冊forall Haskell會自動將它們引入到它通常所用的所有相同位置。

相關問題