使用 getLine 和 putStr 时 IO 发生乱序 [英] IO happens out of order when using getLine and putStr
问题描述
我是一个 Haskell 初学者,我才刚刚开始围绕 Monads 展开我的头脑,但我还没有真正理解它.我正在编写一个游戏,其中包括询问用户输入和响应.这是我的函数的简化版本:
I'm a Haskell beginner, I'm just beginning to wrap my head around Monads, but I don't really get it yet. I'm writing a game that consists of asking the user for input, and responding. Here is a simplified version of my function:
getPoint :: IO Point
getPoint = do
putStr "Enter x: "
xStr <- getLine
putStr "Enter y: "
yStr <- getLine
return $ Point (read xStr) (read yStr)
completeUserTurn :: (Board, Player) -> IO (Board, Player)
completeUserTurn (board, player) = do
putStr $ "Enter some value: "
var1 <- getLine
putStr $ "Enter another value: "
var2 <- getLine
putStr $ "Enter a point this time: "
point <- getPoint
if (... the player entered legal values ...) then do
putStr $ "This is what would happen if you did that: {stuff} do you want to do that? (y/n) "
continue <- getLine
if continue == "y" then
return (...updated board..., ...updated player...)
else
completeUserTurn (board, player)
else do
putStr "Invalid Move!
"
completeUserTurn (board, player)
发生的情况是提示将与应该出现在提示之前的文本乱序显示.
What's happening is that the prompts will appear out of order with the text that is supposed to appear before the prompt.
以下是我编译上述代码后发生的情况的示例:
Here's an example of what's happening after I compiled the code above:
1
输入一些值:输入另一个值:2
3
4
这次输入一个点:输入x:输入y:y
这个对吗?(是/否):
1
Enter some value: Enter another value:2
3
4
Enter a point this time: Enter x: Enter y: y
Is this correct? (y/n):
粗体是我输入的内容.
显然,我有一些重大的概念错误,但我不知道是什么.请注意,它在解释器中正常工作,但在编译时失败.
Obviously, I have some major conceptual error, but I don't know what. Note that it works correctly in the interpreter and fails when compiled.
推荐答案
正如 Michael 所说,问题在于缓冲.默认情况下,输出会被缓冲,直到您打印换行符(或者,如果您有很长的行,则直到缓冲区已满),因此在尝试使用 putStr代码>就像你在做的那样.
As Michael said, the issue is buffering. By default, output is buffered until you print a newline (or until the buffer is full if you have really long lines), so you'll most often see this issue when trying to do same-line prompts using putStr
like you're doing.
我建议定义一个像这样的小辅助函数来为你完成冲洗:
I suggest defining a small helper function like this to take care of doing the flushing for you:
import System.IO
prompt :: String -> IO String
prompt text = do
putStr text
hFlush stdout
getLine
现在你可以简单地做
getPoint = do
xStr <- prompt "Enter x: "
yStr <- prompt "Enter y: "
return $ Point (read xStr) (read yStr)
这篇关于使用 getLine 和 putStr 时 IO 发生乱序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!