I'm learning Haskell through learnyouahaskell.com and wanted to test some of the concepts before finishing the input/output module. I haven't been able to google or hoogle my way out of this question, though, even though it seems quite simple.
When I try to run the following code
getName = do
name <- getLine
return name
the output of getName
becomes an element of type IO String
instead of String
, even though name is definitely a String
By reading the documentation and other StackVverflow's questions I couldn't figure out why is this happening when I declare getName
as a function (when I use the bind <- operation directly on main
there's no problem whatsoever).
The return
function is not conceptually the same as what return does in languages like C++, Java and Python. return :: Monad m => a -> m a
takes an a
(here a String
), and produces an m a
(here IO a
).
The do
notation is syntacticual sugar. If we desugar the statement, you wrote:
getName = getLine >>= (\name -> return name)
or cleaner:
getName = getLine >>= return
The bind function (>>=) :: Monad m => m a -> (a -> m b) -> m b
thus has as first operand an m a
, and as second a function a -> m b
, and produces an m b
. Since getLine :: IO String
is an IO String
, that thus means that m
is the same as IO
, and a
is the same as String
. The return :: Monad m => a -> m a
, makes it clear that here b
is the same as a
.
Then what is IO
here. A metaphor that is frequently used is the one of a recipe. In this metaphor an IO a
is a set of instructions that when you follow these, you will get an a
. But that does not mean that that recipe is an a
.
(>>=)
here basically says that, on the left hand I have a recipe to make a
, on the right hand I have a function that converts that a
into a recipe to make b
, so we can construct a recipe to make b
with these two.
People often ask how to unwrap an a
out of an IO a
, but conceptually it makes not much sense. You can not "unwrap" the cake out of a recipe to make a cake. You can follow the instructions to make a cake. Following instructions is something the main
will eventually do. We thus can construct a (long) recipe the main will do. But we can not unwrap the values.
Strictly speaking there is a function unsafePerformIO :: IO a -> a
that can do that. But it is strongly adviced not to use that. Functions in Haskell are supposed to be pure that means that for the same input, we always retrieve the same output. getLine
itself is a pure, since it always produces the same recipe (IO String
).