2011-03-07 77 views
16

concatMap是做什么用的? 我知道concatmap做什么。它只是将它们放在一起还是完全不同的功能?concatMap是做什么的?

+6

它在行为上与'concatMap f = concat不可区分。地图f'。我不确定它在理论上也更有效率。我想这只是一个便利的组合。 – luqui 2011-03-07 22:53:11

+2

@luqui因为'concatMap'是使用'foldr'实现的,所以可以使用'foldr/build'技术进行优化。因此,它的效率更高:https://ghc.haskell.org/trac/ghc/wiki/FoldrBuildNotes – 2014-11-23 08:41:37

回答

8

从概念上讲,是的,但actual implementation不同的是:

concatMap    :: (a -> [b]) -> [a] -> [b] 
concatMap f    = foldr ((++) . f) [] 
+1

指出为什么'concatMap'是使用'foldr'实现的,原因是short-使用'foldr/build'技术减少森林砍伐:https://ghc.haskell.org/trac/ghc/wiki/FoldrBuildNotes – 2014-11-23 08:40:22

8

检查the documentation显示:

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

地图功能在一个列表并且将结果连接

而且其定义如下:

-- | Map a function over a list and concatenate the results. 
concatMap    :: (a -> [b]) -> [a] -> [b] 
concatMap f    = foldr ((++) . f) [] 

比较下面的输出ghci的:

*Main> concatMap (++"! ") ["one", "two", "three"] 
"one! two! three! " 
*Main> concat $ map (++"! ") ["one", "two", "three"] 
"one! two! three! " 
+4

此外,如果你想知道*为什么它存在,我相信这是因为它是列表实现'>> =',只是给了一个不同的名字。 :) – porges 2011-03-07 22:01:29

14

是的,concatMap功能只是concatmap放在一起。由此得名。将功能一起仅仅意味着将它们组成:

(.) :: (b -> c) -> (a -> b) -> a -> c 

然而concatmap不能简单地使用函数组合放在因为map类型的签名一起:

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

正如你所看到的功能组成预期a -> b类型的函数,但map类型为a -> b -> c。要撰写concatmap您需要使用.:操盘手:

(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d 

concat函数的类型签名:

concat :: [[a]] -> [a] 
      ----- --- 
      c  d 

因此concat .: map的类型为:

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

concatMap相同:

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

.:运营商本身在功能构成方面来写:

(.:) = (.) (.) (.) 

-- or 

(.:) = (.) . (.) 

因此concatMap可以写为:

concatMap = (.) (.) (.) concat map 

-- or 

concatMap = (concat .) . map 

-- or 

concatMap = concat .: map 

如果flipconcatMap参数你得到的>>=(绑定)函数列表monad:

instance Monad [] where 
    return x = [x] 
    (>>=) = flip concatMap 
    fail _ = [] 

flip concatMap :: [a] -> (a -> [b]) -> [b] 

>>= :: Monad m => m a -> (a -> m b) -> m b 

这使得相同的列表单子的=<<功能:

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

=<< :: Monad m => (a -> m b) -> m a -> m b 

所以,现在你知道的一切,有了解concatMap。这只是concat适用于map的结果。由此得名。

+0

优秀的答案。只是一个错字:“**在**你翻转[...]”应该是**如果**。 – YoTengoUnLCD 2018-03-03 19:26:44