2015-08-25 116 views
5

對不起,這個簡單的問題打擾你。我正試圖瞭解類型族擴展如何工作。當我愚弄它時,我遇到了一個錯誤,我無法弄清楚爲什麼。Haskell類型家庭錯誤

class Foo a b c where 
    data T a b c :: * 

    f :: a -> T a b c 

    g :: T a b c -> b 

    h :: c -> a -> b 
    h c a = g $ f a 

錯誤消息:

Could not deduce (Foo a b c0) arising from a use of ‘g’ 
from the context (Foo a b c) 
    bound by the class declaration for ‘Foo’ 
    at DB/Internal/Typecast.hs:(17,1)-(25,19) 
The type variable ‘c0’ is ambiguous 
Relevant bindings include 
    a :: a (bound at DB/Internal/Typecast.hs:25:9) 
    h :: c -> a -> b (bound at DB/Internal/Typecast.hs:25:5) 
In the expression: g 
In the expression: g $ f a 
In an equation for ‘h’: h c a = g $ f a 

我不知道如何爲c在T a b c曖昧g。編譯器能否從T a b cf獲得c的類型?

我只是想g . f

+0

請修正代碼示例中的縮進 - 即發佈實際代碼。發佈代碼而不是實際使用的代碼只是混淆了實際問題。 – Cubic

+1

「編譯器不能從'f'的'T a b c'中得到'c'的類型嗎?」是的,但是'f'從哪裏得到它的'T a b c'? –

+0

@DanielWagner對不起,我不認爲我明白類型家庭是如何工作的。在使用數據關鍵字的實例聲明中聲明的f和g都不是T a b c嗎? – Larry

回答

4

注意的複合材料,其在定義

h :: c -> a -> b 
h c a = g $ f a 

沒有限制,即fg是指您定義h相同實例。 (而這種靈活性經常是定義實例有用。)

從類型推斷的g結果被限制爲同一類型b的,和f參數限制爲a型的,但沒有什麼說T a b c從一個傳遞到另一個使用相同的c

要在這種情況下,解決這個問題,你可以啓用ScopedTypeVariables

h c a = g (f a :: T a b c) 

注意這是因爲數據的家庭是「射」(數據系列的類型參數可以從最終的類型推斷)。如果您使用類型代替系列,即使這樣也不行,因爲T a b c根本不一定會確定c