В чем разница между mapcat в Clojure и concatmap в Haskell?

В Clojure у вас есть функция под названием mapcat в Clojure, которая имеет некоторое сходство с плоская карта в Scala. Это используется для сопоставления функции со списком. и вернуть список.

В Haskell у нас есть функция ConcatMap, имя которой похоже.

Мой вопрос: в чем разница между mapcat в Clojure и concatmap в Haskell?


person hawkeye    schedule 26.12.2013    source источник
comment
Как вы думаете, почему они разные?   -  person Roman Cheplyaka    schedule 26.12.2013
comment
Поскольку mapcat в Clojure и flatmap в Scala отличаются: scala-in-terms" title="в чем разница между mapcat в clojure и flatmap в scala с точки зрения"> stackoverflow.com/questions/20363205/   -  person hawkeye    schedule 26.12.2013
comment
flatMap в Scala — это общее название монадической привязки, которая >>= в Haskell. С другой стороны, concatMap >>= специализируется на [] монаде.   -  person Tom Ellis    schedule 26.12.2013
comment
Итак, вы говорите, что функция Clojure и функция Haskell похожи, за исключением основных различий в структурах данных?   -  person hawkeye    schedule 26.12.2013


Ответы (2)


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
comment
Мне было очень интересно это увидеть. Я все еще не совсем уверен, как читать аннотации типа с множественной арностью — позволяет ли это индивидуально варьировать входные данные для функции карты? - person J. Abrahamson; 27.12.2013
comment
t ... b — это шаблон для последовательности типов. Он обрабатывает любую допустимую арность mapcat, так что аргумент функции соответствует количеству аргументов для mapcat. Статья, описывающая это исследование, называется «Практический полиморфизм переменной арности». - person Ambrose; 31.12.2013
comment
Спасибо! Я возьму читать. В настоящее время я внедряю такую ​​​​систему на работе. - person J. Abrahamson; 31.12.2013

mapcat работает только с последовательностями и всегда возвращает ленивую последовательность.

person Alex Baranosky    schedule 26.12.2013
comment
и всегда возвращает отложенный список. Это не имеет значения, так как concatMap также возвращает отложенный список. - person Alexey Romanov; 26.12.2013
comment
Я не знаю Хаскель. Я просто описываю mapcat в Clojure. - person Alex Baranosky; 27.12.2013