Почему мой ввод-вывод не выполняется по порядку? - PullRequest
5 голосов
/ 25 апреля 2010

У меня проблема с 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

Ответы [ 3 ]

14 голосов
/ 25 апреля 2010

Если проблема в том, что я думаю, то ваша проблема в том, что IO Хаскелла буферизируется: этот вопрос объясняет, что происходит. Когда вы запускаете скомпилированную программу на Haskell, GHC сохраняет вывод в буфере и только периодически сбрасывает его на экран; это происходит, если (а) буфер переполнен, (б) если печатается новая строка, или (в), если вы вызываете hFlush stdout.

Другая проблема, с которой вы можете столкнуться, заключается в том, что getChar может не сработать, пока не будет прочитана новая строка, но тогда новая строка будет в вашем входном потоке; Вы могли бы решить эту проблему с помощью дополнительного getChar, чтобы проглотить новую строку, но, вероятно, должен быть лучший способ.

8 голосов
/ 25 апреля 2010

absz ответ правильный, буферизованный ввод-вывод Хаскелла вызывает у вас проблемы. Вот один из способов переписать ваш doLoop, чтобы получить эффект, который вы ищете:

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

Два изменения: используйте putStrLn, чтобы добавить новую строку и очистить вывод (что, вероятно, то, что вы хотите), и используйте getLine, чтобы захватить ввод строки за раз (снова, вероятно, что вы хотите) .

6 голосов
/ 25 апреля 2010

Буферизация в форме putStr - это ваша проблема, как указывали другие.

Кроме того, точка стиля: putStrLn $ show xs совпадает с print xs

...