I believe you have a problem with foldl
and not with foldM
. foldM
is basically just a very minor variation of foldl
.
So consider:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f x xs
What "happens" is:
- If xs == []
then x
is returned.
- otherwise f
is called as: f x (xs !! 0)
obtaining the result value y :: a
. Then f
is called as: f y (xs !! 1)
, obtaining z
. Then we go for f z (xs !! 2)
etc.
As you can see every call to f
is passed the current result up to that point and the next element from the list in input. So it's used whenever you want to reduce a list into a single value and the computation you want to do is "sequential", i.e. you compute a value from the first element, then from this value and the following element you compute the new value, and from this and the second element you compute a new one etc.
For example:
f ys x = map (+x) ys ++ [x]
foldl f [] [1,2,3]
produces:
[6, 5, 3]
Because:
f [] 1 = [1]
f [1] 2 = [1+2, 2] = [3, 2]
f [3, 2] 3 = [3+3, 2+3, 3] = [6, 5, 3]
To better understand how foldl
and foldr
work, see:
Now, foldM
is the same as foldl
but now the f :: a -> b -> a
has type f :: a -> b -> m a
. This means that the function that combine the current result with the next element is a monadic action, i.e. it can have effects.
For example, consider:
f ys x = do
let a = map (+x) ys ++ [x]
print a
return a
foldM f [] [1,2,3]
What happens is that the text:
[1]
[3,2]
[6,5,3]
gets printed and the value [6, 5, 3]
is the return value of the monadic action.