This code (taken from Learn You A Haskell ):
main = do putStr "Hey, " putStr "I'm " putStrLn "Andy!"
obviously desugars to
main = putStr "Hey, " >>= (\_ -> putStr "I'm " >>= (\_ -> putStrLn "Andy!"))
Which, as I understand it, can be construed as "To putStrLn" by Andy! "First I need to put the STR" I ", and for this I first need to put the STR" Hi ";
I disagree with this interpretation, which is annoying because the compiler obviously does not, and leaves me confused. The problem I am facing is that lambdas ignore their arguments, shouldn't it be recognized and short-circuited during a lazy evaluation?
In addition, of course, the binding returns an IO action, and when this I / O action falls into the ground state, it is executed. But what to stop him from printing "Hey Andy I Am"? I suspect that everything that connects is doing.
Also, how does an IO action like "IO ()" carry enough information to allow the runtime system "Hey, I'm Andy!"? How is this IO () different from IO () than the prints of "Hello World!" or is it written to a file?
Consider another, from the wikipedia page for the monad:
Sugared version:
do putStrLn "What is your name?" name <- getLine putStrLn ("Nice to meet you, " ++ name ++ "!")
Desugared version:
putStrLn "What is your name?" >>= (\_ -> getLine >>= (\name -> putStrLn ("Nice to meet you, " ++ name ++ "!")))
A similar story is here.
I think I just need to see the bind definition for IO, and then everything will be clear. Something else that could help a lot if someone can help me get through how the program really evaluates and identify the exact moments when side effects occur.