使用 getLine 和 putStr 时 IO 发生乱序 [英] IO happens out of order when using getLine and putStr

查看:17
本文介绍了使用 getLine 和 putStr 时 IO 发生乱序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆