5

在 Clojure 中,您在 Clojure 中有一个名为mapcat的函数,它与Scala中的 flatmap 有一些相似之处。它用于将函数映射到列表并返回列表。

在 Haskell 中,我们有一个函数ConcatMap,它的名字看起来很相似

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

4

2 回答 2

10

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

于 2013-12-26T15:09:38.257 回答
1

mapcat只对序列进行操作,并且总是返回一个惰性序列。

于 2013-12-26T10:03:23.157 回答