地图map vs map.map

时间:2019-08-12 09:44:19

标签: function haskell functional-programming

我是Haskell的新手,我认为函数map mapmap.map在Haskell中是相同的。 我的终端机给我两种不同的类型,

(map.map) :: (a -> b) ->  [[a]]  ->  [[b]]

(map map) :: [a -> b] -> [[a] -> [b]]

这些功能在语法方面有什么不同?它们中的每一个到底是什么意思?

2 个答案:

答案 0 :(得分:8)

map map表达式将第二个map作为第一个表达式的参数。因此,这意味着如果我们派生类型,我们将看到:

map :: (  a     ->      b     ) -> ([a] -> [b])
map :: (c -> d) -> ([c] -> [d])
-----------------------------------------------
a ~ (c -> d), b ~ [c] -> [d]

因此,这意味着ac -> 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函数采用两个函数fg,并将它们合并为\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映射的函数)并吐出另一个函数列表(每个函数都在一个特定的内部列表上进行映射) )。