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]]
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.