For the sake of approaching this in yet another way, it can also be helpful to substitute the definitions of bind and return in your expression. If we start with the definitions:
instance Monad [] where
xs >>= f = concat (map f xs)
return x = [x]
Then we can make the following transformations:
[1,2] >>= \n -> [3,4] >>= \m -> return (n,m)
[1,2] >>= \n -> [3,4] >>= \m -> [(n, m)]
[1,2] >>= \n -> concat (map (\m -> [(n, m)]) [3,4])
concat (map (\n -> concat (map (\m -> [(n, m)]) [3,4])) [1,2])
Or perhaps more simply:
concatMap (\n -> concatMap (\m -> [(n, m)]) [3,4]) [1,2]
All of which are valid expressions and produce the same value.
Depending on your learning style this might not be as helpful as the other approaches, but it does take a lot of the mystery out of >>= and return.