对不起,措辞很差,但很难描述。
我想我会跳到这个例子:
add :: Integer -> Integer -> Integer
add x y = x + y
为什么:
:: Integer -> Integer -> Integer
而不是:
:: Integer, Integer -> Integer
箭头是“Function type-mapping operator”,而不是某种分隔符,不是吗?
答案 0 :(得分:21)
因为蜷缩。想想这个的类型:
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]
看看我要去哪里?参数之间没有区别是返回类型。
答案 1 :(得分:16)
我的“啊哈”时刻是我意识到的那一刻
map :: (a -> b) -> [a] -> [b]
明确分组时,实际上看起来更自然:
map :: ( a -> b )
-> ([a]->[b])
它接受一个函数并返回一个列表函数。如果没有明确的定义,这种分组不太有效,是吗?
map :: ( a -> b
,[a])->[b]
然而,这种分组在某种程度上是一种更“深入”,更有用的思考功能的方式。特别是,如果你概括它:
class Functor f where
fmap :: (a->b) -> f a->f b
functor执行两项操作:采用某种类型(例如a
或b
)并将其与其他类型(f a
,f b
相关联) 。但它也需要态射(a -> b
)并将其与另一个态射(f a -> f b
)相关联。
答案 2 :(得分:7)
类型签名更准确地读作
add :: Integer -> (Integer -> Integer)
与
有很大不同add :: (Integer -> Integer) -> Integer
第一个表示一个函数,它接受Integer
并返回一个新函数,该函数接受Integer
并返回Integer
。这是为了便于部分应用功能,所以像
(+) :: Int -> Int -> Int -- specialized to Int
(1 +) :: Int -> Int
> map (1 +) [1..10]
[2,3,4,5,6,7,8,9,10,11]