因为柯里化。考虑一下这个类型:
add 3 :: Integer -> Integer
如果你给add
它返回一个映射一个数字的函数Integer
到另一个整数。所以你可以这样做:
map (add 3) [1..10]
通过部分应用将参数与返回类型区别对待是没有意义的。
编辑以澄清
我认为 bheklilr 提出了一个很好的观点,即类型签名可以这样读
add :: Integer -> (Integer -> Integer)
我们可以采用带有更多参数的函数,zipWith3
因为这是我唯一能真正想到的。
zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
如果我们只读一下它的作用,它需要一个函数,该函数接受 3 个值并分别返回第四个和 3 个这些值的列表,并返回第四个值的列表。尝试一下。
add3 :: Int -> Int -> Int -> Int
add3 a b c = a + b + c
Prelude>zipWith3 add3 [1] [2] [3]
[6]
尽管在这种情况下所有值都是类型Int
它仍然证明了这一点。
现在如果我们不提供所有列表怎么办?如果我们不给它任何列表怎么办?add3
.
zipWith3 add3 :: [Int] -> [Int] -> [Int] -> [Int]
zipWith3 add3 :: [Int] -> ([Int] -> [Int] -> [Int])
zipWith3 add3 :: [Int] -> [Int] -> ([Int] -> [Int])
所以,现在我们有一个函数,它接受 3 个列表并返回一个列表。但这也是一个接受一个列表并返回一个接受 2 个列表并返回一个列表的函数。没有办法真正区分它们。
(zipWith3 add3) [1,2] [3,4] [5,6] :: [Int]
(zipWith3 add3) [1,2] :: [Int] -> [Int] -> [Int]
明白我要说的是什么吗?参数和返回类型之间没有区别。