【问题标题】:Execution order with (>>=) not what I expected(>>=) 的执行顺序不是我所期望的
【发布时间】:2011-12-02 19:26:29
【问题描述】:

我收到了一系列网络请求,每个请求都需要 10 秒以上。
为了让用户知道发生了什么,我提供了更新:

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

使用 GHCi 可以按预期工作,但是编译或使用 runghc 时,“Downloading”在“DONE”之前不会打印。

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

发生了什么事?

【问题讨论】:

标签: haskell monads do-notation


【解决方案1】:

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

默认情况下,终端 IO 是行缓冲的。这意味着在您打印换行符或刷新缓冲区之前,屏幕上不会出现任何输出。因此,您需要在执行putStr 后使用hFlush 刷新'输出流,或者您需要使用hSetBuffering 更改stdout 的缓冲模式以不使用行缓冲。

【讨论】:

  • 顺便提一下,Haskell 在 I/O 缓冲中没有什么特别之处,在 CC++Python 等中也是如此。
  • @MatveyB.Aksenov:嗯,这里真正的问题是,当从 REPL 提示符运行程序与作为编译的二进制文件运行程序时,缓冲行为不同。也不是特定于 Haskell,但由于人们在 Haskell 中的发展方式,这是一个长期的陷阱。
  • 好吧,REPL 和编译后的二进制文件之间的大部分内容都不同。从缓冲到空间使用、优化和性能,甚至(或特别是)类型默认。
  • @Thomas M. DuBuisson:但其中大多数要么非常明显,要么不会改变程序的明显行为,而缓冲的东西往往会让人们大吃一惊。不过,GHCi 的类型默认也确实会产生很多 SO 问题。
  • @Thomas M. DuBuisson:空间使用、优化和性能是内部因素。我不希望在 GHCi 中调整我的代码的性能,但我希望能够测试它的行为。我同意类型默认是一个雷区,特别是因为 GHCi 被广泛用于检查代码中的类型。
猜你喜欢
  • 1970-01-01
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多