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] 后它才会输出 $ 以及我写的任何内容。

似乎getLineputStr "$ " 之前被调用,即使IO monad 保证它的动作是按照它们在代码中的排序顺序调用的(或者我明白here 写的是什么) .那么为什么它不能正常工作呢?

【问题讨论】:

顺便说一句,在我尝试自己运行代码之前,我实际上并不相信你。然后我居然说“哇啊啊……?!”在我的隔间里大声说出来。把你的问题提炼成这样一个很好的、易消化的、令人惊讶的形式,做得很好! 谢谢。这也让我感到惊讶。实际上,我开始相信这毕竟不是 Haskell 的“错误”,而是我以前不知道的其他一些 shell/终端/OS 陷阱。 :) 【参考方案1】:

实际上,putStrhFlush 操作 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() 方法的执行顺序

Haskell语言学习笔记(19)File IO

java 运行程序报错的修改顺序

java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序

bat批处理文件按顺序执行exe

线程优先级的高低和执行顺序的关系