Execution order with (>>=) not what I expected
Asked Answered
P

1

9

I've got a series of network requests, that each take >10 seconds.
So that the user knows what's happening, I give updates:

main = do putStr "Downloading the first thing... "
          {- Net request -}
          putStrLn "DONE"
          putStr "Downloading the second thing... "
          {- Net request -}
          putStrLn "DONE"

With GHCi this works as expected, but compiled or with runghc, "Downloading" doesn't print till "DONE" does.

I've rewritten it with (>>=) and (>>), but I get the same problem.

What's going on?

Paganism answered 2/12, 2011 at 19:26 Comment(1)
Related: #2707135Tami
L
16

The problem here isn't with the execution order. The statements execute in exactly the order you expect. The problem is that due to buffering, you don't actually see the results as soon as they happen.

Specifically terminal IO is line-buffered by default. This means that no output will appear on the screen until you print a newline or flush the buffer. So you need to either flush the´output stream using hFlush after executing putStr or you need to change stdout's buffering mode using hSetBuffering to not use line buffering.

Landrum answered 2/12, 2011 at 19:29 Comment(5)
Just to mention there is nothing specific to Haskell in I/O buffering, it's same in C, C++, Python, etc.Vince
@MatveyB.Aksenov: Well, the real issue here is that the buffering behavior differs when running a program from the REPL prompt vs. as a compiled binary. Also not specific to Haskell, but it is a chronic pitfall because of how people develop in Haskell.Perigordian
Well most everything differs between the REPL and a compiled binary. From buffering to space use, optimizations and performance, and even (or, especially) type defaulting.Esp
@Thomas M. DuBuisson: But most of those are either really obvious or don't change the apparent behavior of the program, whereas the buffering thing tends to catch people by surprise. GHCi's type defaulting does create a lot of SO questions as well, though.Perigordian
@Thomas M. DuBuisson: space use, optimizations, and performance are internals. I wouldn't expect to tune the performance of my code in GHCi, but I'd expect to be able to test its behavior. I agree that type-defaulting is a minefield, particularly since GHCi is used so extensively for checking types in code.Paganism

© 2022 - 2024 — McMap. All rights reserved.