concatMap
是做什么用的? 我知道concat
和map
做什么。它只是将它们放在一起还是完全不同的功能?concatMap是做什么的?
回答
从概念上讲,是的,但actual implementation不同的是:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = foldr ((++) . f) []
指出为什么'concatMap'是使用'foldr'实现的,原因是short-使用'foldr/build'技术减少森林砍伐:https://ghc.haskell.org/trac/ghc/wiki/FoldrBuildNotes – 2014-11-23 08:40:22
检查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! "
此外,如果你想知道*为什么它存在,我相信这是因为它是列表实现'>> =',只是给了一个不同的名字。 :) – porges 2011-03-07 22:01:29
是的,concatMap
功能只是concat
和map
放在一起。由此得名。将功能一起仅仅意味着将它们组成:
(.) :: (b -> c) -> (a -> b) -> a -> c
然而concat
和map
不能简单地使用函数组合放在因为map
类型的签名一起:
map :: (a -> b) -> [a] -> [b]
-------- --- ---
a b c
正如你所看到的功能组成预期a -> b
类型的函数,但map
类型为a -> b -> c
。要撰写concat
与map
您需要使用.:
操盘手:
(.:) :: (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
如果flip
的concatMap
参数你得到的>>=
(绑定)函数列表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
的结果。由此得名。
优秀的答案。只是一个错字:“**在**你翻转[...]”应该是**如果**。 – YoTengoUnLCD 2018-03-03 19:26:44
- 1. 什么“?”做?什么是__FILE__?
- 2. 什么是setDetailItem:做什么?
- 3. 这是做什么
- 4. 什么是random.random做
- 5. page.driver.reset是什么!做?
- 6. 什么是“GCMRegsistrar.register”做
- 7. 是什么[popViewControllerAnimated];做?
- 8. KeyboardView.closing()是做什么的?
- 9. “gcc -xW”是做什么的?
- 10. 这是做什么用的?
- 11. “disableplugins = pnat”是做什么的?
- 12. clog()的做法是什么?
- 13. CG_INLINE是做什么的?
- 14. fork =“true”是做什么的?
- 15. 嘲笑是做什么的?
- 16. AsynchronousExit()是做什么的?
- 17. NHibernateUtil.Initialize是做什么的?
- 18. “mro()”是做什么的?
- 19. APIENTRY是做什么的?
- 20. AutoFac:PropertyWiringFlags.AllowCircularDependencies是做什么的?
- 21. WS_EX_APPWINDOW是做什么的?
- 22. dis.findlabels()是做什么的?
- 23. FrameLayout是做什么的?
- 24. postInvalidate()是做什么的?
- 25. class_getClassVariable()是做什么的?
- 26. Pyvmomi这是做什么的?
- 27. adodb:createparameter是做什么的?
- 28. GL_COLOR_ATTACHMENT是做什么用的?
- 29. stringWithUTF8String是做什么的?
- 30. pg_basebackup是做什么的?
它在行为上与'concatMap f = concat不可区分。地图f'。我不确定它在理论上也更有效率。我想这只是一个便利的组合。 – luqui 2011-03-07 22:53:11
@luqui因为'concatMap'是使用'foldr'实现的,所以可以使用'foldr/build'技术进行优化。因此,它的效率更高:https://ghc.haskell.org/trac/ghc/wiki/FoldrBuildNotes – 2014-11-23 08:41:37