Now let's experiment a bit. If we run this

import Control.Monad.List

type Lio = ListT IO

test :: Lio ()
test = do
   x <- return [1,2]
   y <- ListT $ return ['a','b']
   lift $ putStrLn (show (x,y))

main = runListT test

we get

([1,2],'a')
([1,2],'b')

Does it seem strange that y iterates through the list ['a','b'] but x does not iterate through the list [1,2]?

The reason is this: the return used in the x assignment exists within a do which must produce an Lio (). It acts like List's return. Therefore its interior object is the single element of the list [[1,2]].

The return in the assignment to y is different in that it must produce something for the ListT constructor, that is to say it must produce an IO a. Therefore it acts like an IO return and so it produces a monadic object whose interior object is ['a','b']. The ListT constructor then builds the Lio monadic object and its interior objects are 'a' and 'b'.

Therefore x is coming from a list whose single element is [1,2] and y is coming from a list whose elements are 'a' an 'b'.

Whew! You really do have to pay attention to Haskell's type system when figuring out what return does.