I\'ve already checked Hoogle, http://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#v:mapM, which says that mapM_
ignores the results.
However,
In more general terms, the difference is that mapM_
only needs to "consume" all elements of the input, whereas mapM
also needs to "re-build" the data structure, with new values. That's pretty much trivial for lists: you only need to traverse along the cons-cells, updating values with those received from the action you map. But it doesn't work that easily for containers whose structure depends on the actual contained values. So e.g. for Data.Set
you can't define the equivalent of mapM
with type (a -> m b) -> Set a -> m (Set b)
– it is an instance of Foldable, but not of Traversable