">>="和concatMap之间的区别"

3

今天我在尝试理解单子的时候玩了一下 >>=,发现了一个有趣的模式。当使用列表单子时,>>= 的行为看起来像是 concatMap。我搜索了一下 hackage 上的定义,试图找到任何相似之处。

我尝试了一些事情:

[1, 2, 3] >>= (iter 5 id) => [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]

concatMap (iter 5 id) [1, 2, 3]=> [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]

[1, 2, 3]通过(iter 5 (+5))迭代生成,结果为[1,6,11,16,21,2,7,12,17,22,3,8,13,18,23]。 使用concatMap (iter 5 (+5) ) [1, 2, 3]也可以得到相同的结果。 此处的iter函数是非无限迭代函数。
iter i f a = toL $ Data.Sequence.iterateN i f a
  where
    toL = Data.Foldable.toList :: Data.Sequence.Seq a -> [a] 

(在repl.it中工作,因此导入出了问题)。

(>>=)在列表中是否等同于concatMap? 它是concatMap的泛化吗?


请参阅 https://en.wikibooks.org/wiki/Haskell/Understanding_monads/List 以深入了解 Monad 在列表类型中的实现。此外,https://wiki.haskell.org/All_About_Monads#List_is_also_a_monad 也提供了相关信息。 - bheklilr
2个回答

9

是的,需要反转参数。比较这些类型签名应该能凸显出相似之处,尽管特殊的列表语法可能会干扰:

Prelude> :t flip concatMap
flip concatMap :: Foldable t => t a -> (a -> [b]) -> [b]
Prelude> :t (>>=)
(>>=)          :: Monad m    => m a -> (a -> m b) -> m b

2
在前缀形式中编写列表类型构造函数(Foldable t => t a -> (a -> [] b) -> [] b)是合法的,只是没有人这样做,因为它会导致更多的括号([] ([] a) vs. [[a]])。 - Jon Purdy

7

是的,(=<<) 是列表的 concatMap>>= 只是任何 Monad 的 fmapjoinconcat 的一般化)的组合,因此这也很直观。


谢谢你提到join,我从来没有意识到过! - Jack Brandt
xs >>= f = join $ fmap f xs - Mateen Ulhaq

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接