RankNTypes

想象一下以下情況:

foo::Show a => (a -> String) -> String -> Int -> IO ()
foo show' string int = do
   putStrLn (show' string)
   putStrLn (show' int)

在這裡,我們希望傳入一個將值轉換為 String 的函式,將該函式應用於字串引數和 int 引數,並將它們列印出來。在我看來,沒有理由這會失敗! 我們有一個函式可以處理我們傳入的兩種型別的引數。

不幸的是,這不會打字檢查! GHC 根據函式體中的第一次出現推斷出 a 型別。也就是說,只要我們點選:

putStrLn (show' string)

GHC 將推斷 show' :: String -> String,因為 stringString。在嘗試使用時,它會繼續爆炸。

RankNTypes 允許你改為按如下方式編寫型別簽名,對所有滿足 show'型別的函式進行量化:

foo :: (forall a. Show a => (a -> String)) -> String -> Int -> IO ()

這是 2 級多型:我們斷言 show'函式必須適用我們函式中的所有 as,並且之前的實現現在可以工作。

RankNTypes 擴充套件允許在型別簽名中任意巢狀 forall ... 塊。換句話說,它允許秩 N 多型性。