想象一下以下情况:
foo :: Show a => (a -> String) -> String -> Int -> IO () foo show' string int = do putStrLn (show' string) putStrLn (show' int)
在这里,我们希望传入一个将值转换为String的函数,将该函数同时应用于string参数和int参数,并同时打印它们。在我看来,这没有理由失败!我们有一个函数可以处理传入的两种参数。
不幸的是,这不会输入检查!GHCa根据其在功能主体中的首次出现来推断类型。也就是说,一旦我们点击:
putStrLn (show' string)
GHC会推断show' :: String -> String,因为string是String。尝试时它会炸毁show' int。
RankNTypes相反,您可以按如下方式编写类型签名,以量化满足该show'类型的所有函数:
foo :: (forall a. Show a => (a -> String)) -> String -> Int -> IO ()
这是2级多态:我们断言,该show'功能必须为所有工作的a小号内我们的功能,和以前的实现,现在的作品。
该RankNTypes扩展允许forall ...在类型签名中任意嵌套块。换句话说,它允许秩N多态性。