以fmap
(Functor
方法)的类型签名为例:
(a -> b) -> f a -> f b
这与以下类型标记有何不同?
a -> b -> f a -> f b
这两种类型签名之间是否有区别?
以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 -> ...
意思是“给定一些a和一些b……”
是的,(a -> b)
表示一个参数,这个参数是一个带有签名 a -> b
的函数;而 a -> b -> ...
表示两个参数。