5

do コンストラクト内であっても、IO が順番に実行されないという問題が発生しました。

次のコードでは、どのカードが残っているかを追跡しています。カードは文字のタプル (1 つはスーツ用、もう 1 つはバリュー用) であり、ユーザーはどのカードがプレイされたかを継続的に尋ねられます。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
4

3 に答える 3

14

問題が私が考えているものである場合、あなたの問題は Haskell の IO がバッファリングされていることです:この質問は何が起こっているかを説明しています。コンパイルされた Haskell プログラムを実行すると、GHC は出力をバッファーに格納し、定期的にのみ画面にフラッシュします。これは、(a) バッファーがいっぱいの場合、(b) 改行が出力された場合、または (c) を呼び出した場合に行われますhFlush stdout

あなたが見ているかもしれない他の問題はgetChar、改行が読み込まれるまで発火しないかもしれないが、改行が入力ストリームにあるということです。改行を飲み込むための追加でこれを解決できるかもしれませんがgetChar、おそらくもっと良い方法があるはずです。

于 2010-04-25T00:06:59.933 に答える
8

absz の答えは正しいです。Haskell のバッファリングされた IO が問題の原因です。doLoop探している効果が得られるように書き換える 1 つの方法を次に示します。

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

2 つの変更:putStrLn改行を追加して出力をフラッシュするために使用し (これはおそらく必要なことです)、getLine一度に 1 行ずつ入力を取得するために使用します (これも、おそらく必要なことです)。

于 2010-04-25T00:23:00.213 に答える
6

他の人が指摘しているように、putStr の形式でのバッファリングが問題です。

また、スタイルポイント:putStrLn $ show xsと同じですprint xs

于 2010-04-25T02:39:12.163 に答える