我是Haskell的新手,我认为函数map map
和map.map
在Haskell中是相同的。
我的终端机给我两种不同的类型,
(map.map) :: (a -> b) -> [[a]] -> [[b]]
和
(map map) :: [a -> b] -> [[a] -> [b]]
这些功能在语法方面有什么不同?它们中的每一个到底是什么意思?
答案 0 :(得分:8)
map map
表达式将第二个map
作为第一个表达式的参数。因此,这意味着如果我们派生类型,我们将看到:
map :: ( a -> b ) -> ([a] -> [b])
map :: (c -> d) -> ([c] -> [d])
-----------------------------------------------
a ~ (c -> d), b ~ [c] -> [d]
因此,这意味着a
与c -> d
具有相同的类型,并且b
与[c] -> [d]
具有相同的类型。因此,这意味着map map
的类型为:
map map :: [a] -> [b]
:: [c -> d] -> [[c] -> [d]]
此处map map
将类型为c -> d
的函数列表作为参数,并将生成一个函数列表,这些函数执行与这些函数的映射。
这意味着如果您写:
(map map) [(+1), (*2), (-3)]
您检索到类似的内容
[map (+1), map (*2), map (-3)]
map . map
并非如此。此表达式等效于(.) map map
。 (.) :: (b -> c) -> (a -> b) -> a -> c
函数采用两个函数f
和g
,并将它们合并为\x -> f (g x)
。因此,该类型表示:
(.) :: ( b -> c ) -> (( a -> b ) -> (a -> c))
map :: (d -> e) -> ([d] -> [e])
map :: (f -> g) -> ([f] -> [g])
-------------------------------------------------------------------------
b ~ d -> e ~ [f] -> [g], c ~ [d] -> [e], a ~ f -> g, d ~ f, e ~ g
(.) map map
的类型为:
(.) map map :: a -> c
:: (f -> g) -> ([d] -> [e])
:: (f -> g) -> ([[f]] -> [[g]])
此函数采用一个类型为f -> g
的单个函数,并将生成一个函数,该函数采用一个f
的列表,并将其映射到g
。
因此(map . map) (+1)
将生成一个函数,用于:
(map . map) (+1) [[1,4,2,5],[1,3,0,2]]
它将生成:
[[2,5,3,6], [2,4,1,3]]
答案 1 :(得分:3)
map . map ≡ (\x -> map (map x))
≡ (\x y -> map (map x) y)
map map ≡ map (map)
≡ (\x -> map map x)
因此,基本上.
将额外的变量走私到外部map
的“功能支架”中。
它将map (map) x
变成map (map x)
。正如类型所表明的,两者的含义都大不相同。
在map (map x) y
中,x
是一个将应用于嵌套列表y
的内部元素的函数,因为map x
(部分应用程序)是一个列表映射功能。而在map map x
中,高阶函数 map
本身被映射到列表中。听起来很奇怪,但是有可能,它只需要一个函数列表(将是内部map
映射的函数)并吐出另一个函数列表(每个函数都在一个特定的内部列表上进行映射) )。