Using return vs. not using return in the list monad

do-notation, haskell, list, monads

Solution

The other answers here are correct, but I wonder if they're not quite what you need... I'll try to keep this as simple as possible, just two points:

Point 1. `return` is not a special thing in the Haskell language. It's not a keyword, and it's not syntactic sugar for something else. It's just a function that's part of the `Monad` typeclass. Its signature is simply:

return :: a -> m a

where `m` is whichever monad we're talking about at the time. It takes a "pure" value and jams it into your monad. (Incidentally, there's another function called `pure` that's basically a synonym for `return`... I like it better because the name is more obvious!) Anyway, if `m` is the list monad, then `return` has this type:

return :: a -> [a]

If it helps, you could think of the type synonym `type List a = [a]`, which might make it slightly more obvious that `List` is the thing we're substituting for `m`. Anyway, if you were going to implement `return` yourself, the only reasonable way you'd implement it is by taking some value (of whatever type `a`) and sticking it in a list by itself:

return a = [a]

So I can say `return 1` in the list monad, and I'll get `[1]`. I can likewise say `return [1, 2, 3]` and I'll get `[[1, 2, 3]]`.

Point 2. `IO` is a monad, but not all monads are `IO`. Many Haskell tutorials seem to conflate the two topics largely for historical reasons (incidentally, the same confusing historical reasons that led to `return` being so poorly named). It sounds like you might have some (understandable) confusion around that.

In your code, you're in the list monad because you wrote `do x <- [1, 2]`. If instead you had written `do x <- getLine` for example, you'd be in the `IO` monad (because `getLine` returns `IO String`). Anyway, you're in the list monad, so you get list's definition of `return` described above. You also get list's definition of `>>=`, which is just (a flipped version of) `concatMap`, defined as:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f xs = concat (map f xs)

The other posted answers pretty much have it covered from here :) I know I didn't answer your question directly, but I'm hoping these two points instead addressed the fundamental things you might have found confusing.

Problem

I started my Grand Haskell Crusade (GHC :) ) and I am a bit confused with monads and IO functions. Could anyone explain simply what is the difference between those two functions? ``` f1 = do x <- [1,2] [x, x+1] -- this is monad, right? f2 = do x <- [1,2] return [x, x+1] ``` The results are: ``` *Main> f1 [1,2,2,3] *Main> f2 [[1,2],[2,3]] ```

Original source