concatMap
в Haskell имеет тип concatMap :: (a -> [b]) -> [a] -> [b]
, в то время как mapcat
в Clojure, если бы он вообще имел какой-либо тип, должен был бы быть намного сложнее. В первом приближении мы могли бы написать
mapcat :: (Collection c, Collection c') => (a -> c' b) -> c a -> [b]
Хотя технически mapCat
наследует список динамических аргументов map
и, таким образом, вообще не может быть напечатан в Haskell, но если бы это было возможно, это могло бы выглядеть так:
mapcat :: (forall c . Collection c => a -> ... -> c b)
-> [forall c . Collection c => c a]
-> [b]
что подчеркивает, насколько динамичным может быть mapCat
, хотя и менее динамичным, чем он есть на самом деле. Тем не менее, если мы обещаем просто передать одну ленивую последовательность в mapcat
, то она идентична concatMap
и имеет почти точно такой же код.
concatMap f s = concat (map f s)
(defn mapcat [f coll] (concat (map f coll)))
Тем не менее, в Haskell никто не использует concatMap
, они используют (>>=)
(или списковые включения, которые при желании можно перевести в (>>=)
).
-- flipped for consistency
flip (>>=) :: Monad m => (a -> m b) -> m a -> m b
Получается, что (>>=)
все же менее полиморфен на входе, чем mapcat
, но (>>=)
тоже полиморфен на выходе. Это позволяет ему иметь гораздо большее семантическое разнообразие. Вы не всегда извлекаете значения из коллекций, запаковываете ответы в список результатов, а затем склеиваете эти результаты вместе. Вместо этого вы можете передать функцию продолжения в недетерминированный параллельный процесс оркестровки. Или анализаторы последовательности, где второй зависит от вывода первого. Или распространять среду с отслеживанием состояния.
person
J. Abrahamson
schedule
26.12.2013
flatMap
в Scala — это общее название монадической привязки, которая>>=
в Haskell. С другой стороны,concatMap
>>=
специализируется на[]
монаде. - person Tom Ellis   schedule 26.12.2013