2010-04-24 2 views
5

У меня возникла проблема с выполнением IO не в порядке, даже внутри конструкции do.Почему мой IO не выполнен в порядке?

В следующем коде я просто отслеживаю, какие карты оставлены, где карта является кортежем символов (один для костюма и один для значения), после чего пользователю постоянно спрашивают, какие карты были сыграны. Я хочу, чтобы 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 

ответ

8

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

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

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

+0

Плохой код! Здесь вы вводите ошибку соответствия шаблону. –

+0

Правда, дело далеко не исчерпывающее, но в качестве доказательства концепции (относительно операций ввода-вывода) оно выполняет эту работу. – perimosocordiae

14

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

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

+0

Yep, хороший вызов. Просто попробовал сам; отлично работает в GHCi, ничего не печатает до конца, когда компилируется, точно так же как и вопрос, с которым вы связались. –

6

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

Кроме того, точка стиль: putStrLn $ show xs такое же, как print xs

Смежные вопросы