Clojure中的mapcat和Haskell中的concatmap有什么区别?

时间:2013-12-26 09:22:34

标签: haskell map clojure concat flatmap

在Clojure中,你在Clojure中有一个名为mapcat的函数,它与flatmap in Scala有一些相似之处。它是used to map a function to a list并返回一个列表。

在Haskell中,我们有一个名为ConcatMap的函数seems quite similar

我的问题是 - Clojure中的mapcat和Haskell中的concatmap有什么区别?

2 个答案:

答案 0 :(得分:10)

Haskell中的

concatMap具有类型concatMap :: (a -> [b]) -> [a] -> [b],而Clojure的mapcat,如果它具有任何类型,则必须要复杂得多。初看起来,我们可以写

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的动态,但仍然不如实际动态。也就是说,如果我们承诺只将一个懒惰的seq传递给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,但(>>=)也是输出多态的。这使它具有更多的语义变化。您并不总是从集合中排出值,将答案压缩到结果列表中,然后将这些结果粘合在一起。您可能会将延续函数传递给非确定性并行编排过程。或者对解析器进行排序,其中第二个取决于第一个的输出。或者传播有状态的环境。

答案 1 :(得分:1)

mapcat仅对序列进行操作,并始终返回lazy-seq。