2012-08-13 59 views
5

爲什麼部分應用不同簽名的功能有效?局部應用說明 - 加入

Control.Monad.join爲例:

GHCi> :t (=<<) 
(=<<) :: Monad m => (a -> m b) -> m a -> m b 
GHCi> :t id 
id :: a -> a 
GHCi> :t (=<<) id 
(=<<) id :: Monad m => m (m b) -> m b 

它爲什麼會接受到位(a -> m b)說法id :: a -> a,因爲他們有明顯的不同?

回答

10

=<<的類型簽名說第一個參數是從a(任何)到b單子的函數。

那麼,m b算作什麼,對吧?因此,我們可以剛剛替補在m b爲每a

(=<<) :: Monad m => (m b -> m b) -> m (m b) -> m b 

id S型說,這是從什麼相同內容的影響。因此,如果我們在m b子(不要忘記單子約束),我們得到:

id :: Monad m => m b -> m b 

然後,你可以看到類型匹配。

+0

聽起來簡單明瞭,謝謝。是否從返回值以某種方式推斷= << id的最後簽名以匹配函數參數的其餘部分? – 2012-08-13 16:41:15

+0

@大衛是的,我相信這基本上是正確的。 – 2012-08-13 16:50:48

2

它試圖統一am b,索性決定a必須m b,所以類型(假設a ~ m b下)爲Monad m => (mb -> m b) -> m (m b) -> m b,一旦你把它應用到id,你只剩下Monad m => m (m b) -> m b

3

一些有用的概念使用這裏:

  1. 任何類型的具有可變a可以通過用任何其他類型的t取代的a每個實例被轉換成不同的類型。因此,如果您有a -> b -> c類型,則可以分別使用dcInt替換b來獲得類型a -> d -> c或類型a -> b -> Int
  2. 任何兩種可以通過替換相互轉換的類型是等價的。例如,a -> bc -> d是等效的(a-c,b_ d)。
  3. 如果一個類型t可以被轉換成一個類型t',但t'不能轉換回t,那麼我們說t'專業化t。例如,a -> aa -> b的專業化版本。

現在,使用這些非常有用的概念,您的問題的答案非常簡單:即使函數的「本機」類型不完全匹配,它們也是兼容的,因爲它們可以被重寫或專門用於獲取完全符合。 Matt Fenwick的答案顯示了這種情況下的專業化。