执行顺序(>> =)不是我的预期

ami*_*dfv 9 monads haskell do-notation

我有一系列网络请求,每个请求大于10秒.
为了让用户知道发生了什么,我给出了更新:

main = do putStr "Downloading the first thing... "
          {- Net request -}
          putStrLn "DONE"
          putStr "Downloading the second thing... "
          {- Net request -}
          putStrLn "DONE"
Run Code Online (Sandbox Code Playgroud)

使用GHCi,这可以按预期工作,但编译或使用runghc,"下载"不打印直到"完成".

我用(>> =)和(>>)重写了它,但是我遇到了同样的问题.

这是怎么回事?

sep*_*p2k 16

这里的问题不在于执行顺序.语句按照您期望的顺序执行.问题在于,由于缓冲,您实际上并不会在结果发生时立即看到结果.

特别是终端IO默认为线路缓冲.这意味着在打印换行符或刷新缓冲区之前,屏幕上不会显示任何输出.所以你需要hFlush在执行后使用刷新'输出流,putStr或者你需要使用hSetBuffering不使用行缓冲来改变stdout的缓冲模式.

  • 只是提到在I/O缓冲中没有特定的"Haskell",在"C","C++","Python"等中也是如此. (10认同)
  • @ MatveyB.Aksenov:嗯,这里真正的问题是,当从REPL提示符运行程序时,缓冲行为会有所不同,而不是编译后的二进制文件.也不是Haskell特有的,但由于人们在Haskell中的发展,这是一个长期的陷阱. (5认同)
  • 在REPL和编译的二进制文件之间,大多数情况都有所不同.从缓冲到空间使用,优化和性能,甚至(或特别是)类型默认. (2认同)
  • @Thomas M. DuBuisson:但其中大多数要么是显而易见的,要么不会改变程序的明显行为,而缓冲的东西往往让人感到意外.不过,GHCi的类型默认确实也会产生很多SO问题. (2认同)
  • @Thomas M. DuBuisson:空间使用,优化和性能是内部的.我不希望在GHCi中调整我的代码的性能,但我希望能够测试它的行为.我同意类型默认是一个雷区,特别是因为GHCi被广泛用于检查代码中的类型. (2认同)