Haskell IO 执行顺序
Posted
技术标签:
【中文标题】Haskell IO 执行顺序【英文标题】:Haskell IO execution order 【发布时间】:2016-03-04 17:02:36 【问题描述】:我有以下代码:
import Control.Monad (unless)
import System.IO (isEOF, hFlush, stdout)
main :: IO ()
main = unlessFinished $ do
putStr "$ "
hFlush stdout
getLine >>= putStrLn
main
where
unlessFinished action = isEOF >>= flip unless action
当我编译并运行这段代码时,它会在空白行的开头显示一个光标,并且只有在我按下 [Enter] 后它才会输出 $
以及我写的任何内容。
似乎getLine
在putStr "$ "
之前被调用,即使IO
monad 保证它的动作是按照它们在代码中的排序顺序调用的(或者我明白here 写的是什么) .那么为什么它不能正常工作呢?
【问题讨论】:
顺便说一句,在我尝试自己运行代码之前,我实际上并不相信你。然后我居然说“哇啊啊……?!”在我的隔间里大声说出来。把你的问题提炼成这样一个很好的、易消化的、令人惊讶的形式,做得很好! 谢谢。这也让我感到惊讶。实际上,我开始相信这毕竟不是 Haskell 的“错误”,而是我以前不知道的其他一些 shell/终端/OS 陷阱。 :) 【参考方案1】:实际上,putStr
和 hFlush
操作 在 getLine
操作之前执行 - 但是,isEOF
正在执行之前,并且它不会返回,直到它知道输入是否为EOF
,也就是说,直到你输入一行。您可以考虑将isEOF
移到getLine
之前,如下所示:
main :: IO ()
main = do
putStr "$ "
hFlush stdout
unlessFinished $ do
getLine >>= putStrLn
main
where
unlessFinished action = isEOF >>= flip unless action
【讨论】:
非常简单的解释!我已经在想我自己怎么想不到。事实证明,Haskell 对我的陷阱仍然比我预期的要多。非常感谢。 :)以上是关于Haskell IO 执行顺序的主要内容,如果未能解决你的问题,请参考以下文章
Closeable 和 AutoCloseable close() 方法的执行顺序