2011-03-07 35 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