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。