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

发布于 2024-08-30 07:41:08 字数 532 浏览 2 评论 0原文

我遇到了 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

I got a problem with IO not executing in order, even inside a do construct.

In the following code I am just keeping track of what cards are left, where the card is a tuple of chars (one for suit and one for value) then the user is continously asked for which cards have been played. I want the putStr to be executed between each input, and not at the very end like it is now.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最丧也最甜 2024-09-06 07:41:08

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

您可能会看到的另一个问题是,在读取换行符之前,getChar 可能不会触发,但随后换行符位于您的输入流中;您也许可以使用额外的 getChar 来吞掉换行符来解决此问题,但可能应该有更好的方法。

If the problem is what I think it is, your problem is that Haskell's IO is buffered: this question explains what's happening. When you run a compiled Haskell program, GHC stores output in the buffer and only periodically flushes it to the screen; it does so if (a) the buffer is too full, (b) if a newline is printed, or (c) if you call hFlush stdout.

The other problem you may be seeing is that getChar may not fire until a newline is read, but then the newline is in your input stream; you could perhaps solve this with an extra getChar to swallow the newline, but there should probably be a better way.

我是有多爱你 2024-09-06 07:41:08

absz 的答案是正确的,Haskell 的缓冲 IO 才是给你带来麻烦的原因。这是重写 doLoop 以获得您想要的效果的一种方法:

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

两个更改:使用 putStrLn 附加换行符并刷新输出(这可能是你想要的),并使用 getLine 一次抓取一行输入(同样,可能是你想要的)。

absz's answer is correct, Haskell's buffered IO is what's causing you trouble. Here's one way to rewrite your doLoop to have the effect you're looking for:

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

The two changes: use putStrLn to append a newline and flush the output (which is probably what you want), and use getLine to grab the input a line at a time (again, probably what you want).

陌若浮生 2024-09-06 07:41:08

正如其他人指出的那样,以 putStr 形式进行缓冲是您的问题。

另外,样式点:putStrLn $ show xsprint xs 相同

Buffering, in the form of putStr, is your problem, as others have pointed out.

Also, a style point: putStrLn $ show xs is the same as print xs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文