在rankN
的情況下,f
必須是一個多態函數,它對所有數字類型n
有效。
在rank1
的情況下f
只需定義爲單個數字類型。
下面是一些代碼,說明了這一點:
{-# LANGUAGE RankNTypes #-}
rankN :: (forall n. Num n => n -> n) -> (Int, Double)
rankN = undefined
rank1 :: forall n. Num n => (n -> n) -> (Int, Double)
rank1 = undefined
foo :: Int -> Int -- monomorphic
foo n = n + 1
test1 = rank1 foo -- OK
test2 = rankN foo -- does not type check
test3 = rankN (+1) -- OK since (+1) is polymorphic
更新
在迴應@ helpwithhaskell在評論問題...
考慮一下這個功能:
bar :: (forall n. Num n => n -> n) -> (Int, Double) -> (Int, Double)
bar f (i,d) = (f i, f d)
也就是說,我們應用f
雙方一個Int和雙。如果不使用RankNTypes它不會鍵入檢查:
-- doesn't work
bar' :: ??? -> (Int, Double) -> (Int, Double)
bar' f (i,d) = (f i, f d)
無下列簽名工作,爲???:
Num n => (n -> n)
Int -> Int
Double -> Double
將函數的主體想象爲:'(f(1 :: Int),f(1.0 :: Double))''。你不能使用後者的類型簽名。在'Num n => n - > n - >(Int,Double)''中,'n'必須同時是'Int'和'Double' * *。使用'(forall n。num n => n - > n) - >(Int,Double)'你可以將函數'f'應用於不同的類型,因此它的輸入很好。 – Bakuriu