Подтвердить что ты не робот

Что делает concatMap?

Что делает concatMap? Я знаю, что делают concat и map. Разве только они вместе взяты или это совершенно другая функция?

4b9b3361

Ответ 1

Концептуально, да, , но фактическая реализация actual implementation отличается:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f =  foldr ((++) . f) []

Ответ 2

Да, функция 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, вы получаете функцию >>= (связывание) монады списка:

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. Отсюда и название.

Ответ 3

Проверка документации показывает:

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! "