Haskell concatMap做什么?
Haskell concatMap做什么?,haskell,Haskell,concatMap做什么? 我知道什么是concat和map做的。这只是两者的结合还是完全不同的功能?从概念上讲,是的,但不同的是: concatMap :: (a -> [b]) -> [a] -> [b] concatMap f = foldr ((++) . f) [] 检查显示: 将函数映射到列表并连接结果 其定义如下: -- | Map a function over a list and concatenate the results. concatMap
concatMap
做什么?
我知道什么是
concat
和map
做的。这只是两者的结合还是完全不同的功能?从概念上讲,是的,但不同的是:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = foldr ((++) . f) []
检查显示:
将函数映射到列表并连接结果
其定义如下:
-- | 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! "
是的,
concatMap
功能只是将concat
和map
放在一起。因此得名。将函数放在一起仅仅意味着组合它们:
(.) :: (b -> c) -> (a -> b) -> a -> c
但是,由于map
的类型签名,concat
和map
不能通过简单的函数组合来组合在一起:
map :: (a -> b) -> [a] -> [b]
-------- --- ---
a b c
concatMap :: (a -> [b]) -> [a] -> [b]
正如您所看到的,函数组合要求函数的类型为a->b
,但map
的类型为a->b->c
。要使用map
组合concat
,您需要使用:
操作符:
(.:) :: (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
的相同:
map :: (a -> b) -> [a] -> [b]
-------- --- ---
a b c
concatMap :: (a -> [b]) -> [a] -> [b]
:
运算符本身可以按照函数组合编写:
(.:) = (.) (.) (.)
-- or
(.:) = (.) . (.)
因此,concatMap
可以写成:
concatMap = (.) (.) (.) concat map
-- or
concatMap = (concat .) . map
-- or
concatMap = concat .: map
如果flip
翻转concatMap
的参数,则会得到list monad的>=
(bind)函数:
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
这与列表monad的=
[a]->[b]
=(a->m b)->m a->m b
现在,您知道了有关
concatMap
的所有内容。它只是concat
应用于map
的结果。因此命名。如果您想知道它为什么存在,我相信这是因为它是>=
的列表实现,只是给了一个不同的名称。:)它在行为上与concatMap f=concat无法区分。地图f
。我也不确定它在理论上是否更有效。我想这只是一个方便的组合。@luqui因为concatMap
是使用foldr
实现的,它可以使用foldr/build
技术进行优化。因此,是的,它更有效:说明为什么使用foldr
实现concatMap
,这可能是有用的,原因是使用foldr/build
技术实现了捷径毁林:回答很好。只是一个输入错误:“在你翻转[…]”应该是If。