以fmap
(Functor
方法)的类型签名为例:
(a -> b) -> f a -> f b
与以下类型签名有何不同?
a -> b -> f a -> f b
这两种类型的签名之间是否存在差异?
是的,是有区别的,因为该->
类型的构造函数是右结合.换一种说法,
a -> b -> f a -> f b
相当于
a -> (b -> (f a -> f b))
此类型签名表示一个函数,它接受一个类型的参数a
并返回一个函数,该函数本身接受一个类型的参数b
并返回一个函数,该函数本身接受一个类型的参数f a
并返回一个类型的值f b
.
另一方面,
(a -> b) -> f a -> f b
表示一个函数,它接受一个类型的参数a -> b
(即一个接受类型参数a
并返回一个类型的值的b
函数)并返回一个函数,该函数本身接受一个类型的参数f a
并返回一个类型的值f b
.
这是一个人为的例子,说明了两种类型签名之间的区别:
f :: (Int -> Bool) -> [Int] -> [Bool]
f = map
g :: Int -> Bool -> [Int] -> [Bool]
g n b = map (\n' -> (n' == n) == b)
?> let ns = [42, 13, 42, 17]
?> f (== 42) ns
[True,False,True,False]
?> g 42 True ns
[True,False,True,False]
?> g 42 False ns
[False,True,False,True]
是,
(a -> b) -> ...
意思是"给定一个需要a到b ...的功能".虽然,这个
a -> b -> ...
意思是"给予一些和一些b ......"
是的,这(a -> b)
意味着一个参数是带签名的函数a -> b
,而a -> b -> ...
意味着两个参数.