map与mapM行为

tit*_*coy 31 monads haskell map

我正在使用Real World Haskell的I/O章节.Monads在本书中未讨论另外7章.也就是说,我对I/O的理解充其量是不完整的.

现在我正在尝试理解mapM功能.据我所知,函数"执行"列表中的每个元素必须是"动作"(IO monad).

没有意义的是这个例子.为什么mapM返回的结果与映射相同的参数不同?

Prelude> map (\x -> [x]) [0, 1, 2]
[[0],[1],[2]]
Prelude> mapM (\x -> [x]) [0, 1, 2]
[[0,1,2]]

sep*_*p2k 20

据我所知,函数"执行"列表中的每个元素必须是"动作"(IO monad).

对于IO来说也是如此,但是在你的代码示例中你不使用IO monad,你使用list monad(你给mapM的函数返回一个list([x]),而不是IO).

mapM被定义为mapM f as = sequence (map f as).如果f返回IO,则意味着对于列表中的每个元素,它通过将f应用于元素来构造IO.然后它将使用序列将映射返回的IO列表转换为包含"列表"的IO(因此,当您执行IO时,将返回包含非IO值的列表).

对于列表,它意味着它通过应用于f每个元素来创建列表列表as.然后,它sequence用于创建列表列表,其中包含在列表列表中获取每个列表的一个元素的所有可能方法(例如,sequence [[1,2],[3,4]]返回[[1,3],[1,4],[2,3],[2,4]]).

  • 为了扩展这一点.根据mapM的定义,将序列类型:sequence ::(Monad m)=> [ma] - > m [a]应用于给定的示例.mapM(\ x - > [x])[0,1,2] = sequence(map(\ x - > [x])[0,1,2])= sequence [[0],[1],[ 2]] = [[0,1,2]] (4认同)
  • Matthew S:您的评论非常有帮助,谢谢。 (2认同)

sig*_*fpe 15

可能值得明确的是,这两个片段不是"类似的",你不应该期待相关的结果.特别是'monadic'版本

map(\ x - > [x])[0,1,2]

mapM(\ x - > return [x])[0,1,2]

请注意额外的return.

一般来说,return (map f x)是一样的mapM (return . f) x.

这是因为名单单子,x >>= f"变平"申请的结果fx.当你遗漏时return,申请的结果\x -> [x]被平铺到结果中.有一个额外的return取消额外的扁平化.