我遇到的问题是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
答案 0 :(得分:14)
如果问题出现在我认为的问题上,你的问题就是Haskell的IO被缓冲了:this question解释了发生了什么。当您运行已编译的Haskell程序时,GHC将输出存储在缓冲区中,并仅定期将其刷新到屏幕上;如果(a)缓冲区太满,(b)打印换行符,或(c)拨打hFlush stdout
,则会这样做。
您可能会看到的另一个问题是getChar
在读取换行符之前可能无法触发,但新行在您的输入流中;你也许可以通过额外的getChar
解决这个问题来吞下换行符,但应该有更好的方法。
答案 1 :(得分:8)
absz的答案是正确的,Haskell的缓冲IO是导致你麻烦的原因。这是重写doLoop
以获得您正在寻找的效果的一种方法:
doLoop xs = do putStrLn $ show xs
input <- getLine
let s:n:_ = input
doLoop $ remove (s,n) xs
这两个更改:使用putStrLn
附加换行符并刷新输出(这可能是您想要的),并使用getLine
一次获取一行(同样可能你想要的是什么。
答案 2 :(得分:6)
正如其他人所指出的那样,以putStr的形式缓冲是你的问题。
此外,样式点:putStrLn $ show xs
与print xs