【发布时间】:2016-01-31 12:21:19
【问题描述】:
在使用 GHC 扩展程序时,我遇到了RankNTypes at the School of Haskell,它有以下示例:
main = print $ rankN (+1)
rankN :: (forall n. Num n => n -> n) -> (Int, Double)
rankN f = (f 1, f 1.0)
文章为rankN提供了另一种类型:
rankN :: forall n. Num n => (n -> n) -> (Int, Double)
区别的解释是
后一个签名需要一个从 n 到 n 的函数,对于一些 Num n;前一个签名要求每个 Num n 都有一个从 n 到 n 的函数。
我可以理解,前一种类型需要签名才能成为括号中的内容或更一般的内容。我不明白后一个签名只需要一个函数n -> n 用于“一些Num n”的解释。有人可以详细说明和澄清吗?你如何“阅读”这个以前的签名,让它听起来像它的意思?后一个签名是否与简单的Num n => (n -> n) -> (Int, Double) 相同而无需forall?
【问题讨论】:
-
把函数体想象成:
(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应用于不同的类型,因此它的类型很好。