I'm on the I/O chapter of Real World Haskell. Monads aren't discussed in the book for another 7 chapters. Which is to say, my understanding of I/O is, at best, incomplete.
Right now I am trying to comprehend the mapM function. As I understand it, the function "executes" each element in the list which must be an "action" (IO monad).
What doesn't make sense is this example. Why does mapM return a different result than map for the same arguments?
Prelude> map (\x -> [x]) [0, 1, 2] [[0],[1],[2]] Prelude> mapM (\x -> [x]) [0, 1, 2] [[0,1,2]]
As I understand it, the function "executes" each element in the list which must be an "action" (IO monad).
That's true for IO, but in your code example you don't use the IO monad, you use the list monad (the function you give to mapM returns a list ([x]
), not an IO).
mapM
is defined as mapM f as = sequence (map f as)
. If f returns an IO this means that for each element in the list it constructs an IO by applying f to the element. It then turns the list of IOs that map returns into an IO "containing" a list using sequence (so when you execute the IO, you get back a list containing non-IO values).
For lists it means that it creates a list of lists by applying f
to each element of as
. It then uses sequence
to create a list of lists which contains all possible ways to take one element of each list in the lists of lists (e.g. sequence [[1,2],[3,4]]
returns [[1,3],[1,4],[2,3],[2,4]]
).