Haskell IO执行顺序

Haskell IO execution order

我有以下代码:

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)。那么为什么它不能正常工作?

实际上,putStrhFlush 操作 getLine 操作之前执行的——但是,isEOF在任何一个之前都在执行,并且它不会 return 直到它知道输入是否是 EOF ,也就是说,直到你输入一行。您可以考虑将 isEOF 移动到 getLine 之前,如下所示:

main :: IO ()
main = do
    putStr "$ "
    hFlush stdout
    unlessFinished $ do
        getLine >>= putStrLn
        main
    where
    unlessFinished action = isEOF >>= flip unless action