我是一个 Haskell 初学者,我刚刚开始了解 Monad,但我还没有真正理解它。我正在编写一个游戏,其中包括询问用户输入并做出响应。这是我的函数的简化版本:
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!\n"
completeUserTurn (board, player)
所发生的情况是,提示的显示顺序与应该出现在提示之前的文本的顺序不符。
下面是我编译上面的代码后发生的情况的示例:
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):
粗体是我输入的内容。
显然,我有一些重大的概念错误,但我不知道是什么。请注意,它在解释器中工作正常,但在编译时失败。
最佳答案
正如迈克尔所说,问题在于缓冲。默认情况下,输出会被缓冲,直到您打印换行符(或者如果您的行很长,则直到缓冲区已满),因此在尝试使用 putStr
执行同一行提示时,您最常会看到此问题。就像你正在做的那样。
我建议定义一个像这样的小辅助函数来负责为您进行刷新:
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)
关于haskell - 使用 getLine 和 putStr 时发生 IO 乱序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13190314/