2010-04-24 8 views
5

Mam problem z IO nie wykonywania w kolejności, nawet wewnątrz konstrukcji.Dlaczego moje IO nie jest wykonane w kolejności?

W poniższym kodzie po prostu śledzę, jakie karty zostały, gdzie karta jest krotką znaków (jeden dla koloru i jeden dla wartości), a następnie użytkownik jest stale zapytany, które karty zostały zagrane. Chcę, aby putStr było wykonywane między każdym wejściem, a nie na samym końcu, tak jak jest teraz.

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 

Odpowiedz

8

Odpowiedź absza jest prawidłowa, buforowana IO Haskella jest przyczyną problemów. Oto jeden ze sposobów, aby przepisać doLoop mieć efekt, którego szukasz:

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

dwóch zmian: use putStrLn dołączyć do nowej linii i przepłukać wyjście (co jest chyba to, co chcesz) i używać getLine chwytać dane wejściowe po linii na raz (znowu, prawdopodobnie to, co chcesz).

+0

Zły kod! Wprowadzasz tutaj błąd dopasowywania wzorca potęgowego. –

+0

To prawda, że ​​sprawa nie jest wyczerpująca, ale jako dowód koncepcji (w odniesieniu do operacji IO) spełnia swoją rolę. – perimosocordiae

14

Jeśli problem jest to, co myślę, że to jest Twój problem polega na tym Haskell'a IO są buforowane: this question wyjaśnia, co się dzieje. Po uruchomieniu skompilowanego programu Haskell GHC przechowuje dane wyjściowe w buforze i tylko okresowo opróżnia je na ekran; robi to, jeśli (a) bufor jest zbyt pełny, (b) jeśli drukowany jest nowy wiersz, lub (c) jeśli zadzwonisz pod numer hFlush stdout.

Innym problemem może być to, że getChar może nie uruchamiać się, dopóki nie zostanie odczytany nowy wiersz, ale wtedy znak nowej linii znajdzie się w twoim strumieniu wejściowym; być może rozwiążesz to z dodatkowym getChar połknięciem nowej linii, ale prawdopodobnie powinien być lepszy sposób.

+0

Tak, dobrej rozmowy. Po prostu wypróbowałem to sam; działa dobrze w GHCi, nic nie drukuje do końca po kompilacji, podobnie jak pytanie, z którym się łączyłeś. –

6

Buforowanie, w formie putStr, jest twoim problemem, jak zauważyli inni.

Również punkt styl: putStrLn $ show xs jest taka sama jak print xs

Powiązane problemy