concatMap
做什么?
我知道concat
和map
做了什么。它们只是放在一起还是完全不同的功能?
答案 0 :(得分:20)
是的,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
这使它与列表monad的=<<
函数相同:
concatMap :: (a -> [b]) -> [a] -> [b]
=<< :: Monad m => (a -> m b) -> m a -> m b
现在你知道关于concatMap
的所有信息。仅concat
应用于map
的结果。因此这个名字。
答案 1 :(得分:12)
概念上是,但actual implementation不同:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = foldr ((++) . f) []
答案 2 :(得分: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! "