Considering the expression:
[0,1..] >>= \i -> [i * 2] In the definition of >>= for List, the lambda function \i -> [i * 2] is mapped over the list argument via fmap, resulting in a list of lists, [[0], [2]..]. So >>= needs to flatten the result using a join function in order to return the list: [0, 2..]
According to this source: "...the definition of bind in terms of fmap and join works for every monad m: ma >>= k = join $ fmap k ma"
So why is it necessary to place the burden of returning a monad on the function supplied to >>=? Why not simply define bind like so?
ma >>= k = fmap k ma This way you don't have to deal with flattening the result.
ma >>= k = join $ fmap k mais more powerful. Your variant is just alias tofmap,ma >>= k = fmap k ma ~ (>>=) = flip fmap.fmapand<$>. Of course in your specific example, those would have sufficed.>>=wasn't defined out of thin error; a function of typea -> m bfor a monadmis a Kleisli arrow, and its use is firmly grounded in category theory. Monads are useful in programming because they "trap" values, making it easy to lift a value into the monad but hard to get out.[0,1..] >>= \i -> [i * 2]doesn't return[[0], [2]..]it returns[0,2,4,6,8,..]just likefmap (*2)would do however with the bind operator you have the option to usereturnto make it return a monad properly so[0,1..] >>= \i -> return [i * 2]would result[[0],[2],[4],[6],[8],..]. Yet withfmapits not the casetake 5 $ (\i -> [i * 2]) <$> [0..]would return[[0],[2],[4],[6],[8],..]