为什么我的IO没有按顺序执行?

Has*_*ant 5 io haskell buffering

我遇到的问题是IO没有按顺序执行,即使在do构造中也是如此.

在下面的代码中,我只是跟踪剩下的卡片,卡片是一个字符元组(一个用于套装,一个用于值)然后用户不断被问到已经播放了哪些卡片.我希望putStr在每个输入之间执行,而不是像现在这样在最后执行.

module Main where
main = doLoop cards
doLoop xs = do  putStr $ show xs
                s <- getChar
                n <- getChar
                doLoop $ remove (s,n) xs
suits = "SCDH"
vals = "A23456789JQK"
cards = [(s,n) | s <- suits, n <- vals]
type Card = (Char,Char)
remove :: Card -> [Card] -> [Card]
remove card xs = filter (/= card) xs
Run Code Online (Sandbox Code Playgroud)

Ant*_*sky 14

如果问题是我认为的问题,你的问题是Haskell的IO被缓冲:这个问题解释了发生了什么.当您运行已编译的Haskell程序时,GHC将输出存储在缓冲区中,并仅定期将其刷新到屏幕上; 如果(a)缓冲区太满,(b)打印换行符,或(c)如果打电话,则会这样做hFlush stdout.

您可能看到的另一个问题是,getChar在读取换行符之前可能不会触发,但是换行符在输入流中; 你也许可以用一个额外的东西getChar来解决这个问题,但是应该有一个更好的方法.


per*_*iae 8

absz的答案是正确的,Haskell的缓冲IO是导致你麻烦的原因.这是重写你doLoop有一个你正在寻找的效果的一种方法:

doLoop xs = do  putStrLn $ show xs
                input <- getLine
                let s:n:_ = input
                doLoop $ remove (s,n) xs
Run Code Online (Sandbox Code Playgroud)

这两个更改:用于putStrLn附加换行符并刷新输出(这可能是您想要的),并用于一次getLine获取一行(同样可能是您想要的).


Don*_*art 6

正如其他人所指出的那样,以putStr的形式缓冲是你的问题.

另外,一个样式点:putStrLn $ show xs与之相同print xs