在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