2010-07-14 44 views
4

它通常似乎以下是非法的:Haskell類定義中的隱式類型參數?

class Foo a where 
    foo :: a -> b -> a 

這是合理的;我們怎麼知道b是什麼?

但是,如果我們看一下仿函數的定義:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

我們看到ab顯示出來,即使我們只指定f作爲一個類型變量。我猜這是允許的,因爲編譯器看到例如f a,並且可以發現f本身必須採用a,所以在我們的Functor定義中的其他地方使用a是安全的。我對麼?

回答

6

讓我們分別看看每條線。

class Functor f where 

這聲明瞭一個單參數類型的類Functor;滿足它的類型將被稱爲f

fmap :: (a -> b) -> f a -> f b 

像任何函數定義,所有空閒類型變量隱含forall ED-他們可以和任何被替換。但是,由於第一行,f在範圍內。因此,fmap的類型簽名爲fmap :: forall a b. Functor f => (a -> b) -> f a -> f b。換句話說,每一個函子需要具有fmap定義它可以爲任何ab,並f工作必須(一種類型)* -> *;也就是說,它必須是另一種類型,例如[]MaybeIO

那麼你說什麼是不正確的; a不是特別的,如果我們在Functor中有另一個功能,它將看不到相同的ab。然而,編譯器確實使用f a位來找出什麼樣的f必須是。此外,您的Foo類完全合法;我可以按如下

instance Foo (a -> b) where 
    foo f _ = f 

這滿足foo :: a -> b -> a任何b指定實例;請注意0​​中的b是不同的。誠然,這不是一個非常有趣的例子,但它是完全合法的。

3

它不需要「知道」。它只需要檢查(即不能錯誤地檢查)。 b可以是任何東西;功能foo必須能夠將任何類型作爲第二個參數。

考慮const功能從前奏:

const   :: a -> b -> a 
const x _  = x 

它是如何 「知道」 什麼b(或a,對於這個問題)是什麼?