2010-04-24 12 views
5

J'ai un problème avec les E/S qui ne s'exécutent pas dans l'ordre, même dans un construit.Pourquoi mon E/S n'est-elle pas exécutée dans l'ordre?

Dans le code suivant, je ne fais que suivre les cartes restantes, où la carte est un jeu de caractères (un pour la couleur et un pour la valeur), l'utilisateur est continuellement demandé quelles cartes ont été jouées. Je veux que le putStr soit exécuté entre chaque entrée, et pas à la toute fin comme c'est le cas maintenant.

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 

Répondre

8

La réponse d'absz est correcte, l'E/S tamponnée de Haskell est ce qui vous cause des problèmes. Voici une façon de réécrire votre doLoop d'avoir l'effet que vous recherchez:

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

Les deux changements: utiliser putStrLn pour ajouter une nouvelle ligne et rincer la sortie (ce qui est probablement ce que vous voulez), et utiliser getLine saisir l'entrée une ligne à la fois (encore une fois, probablement ce que vous voulez).

+0

Mauvais code! Vous introduisez un échec de correspondance de modèle potentiel ici. –

+0

Certes, le cas est loin d'être exhaustif, mais en tant que preuve de concept (en ce qui concerne les opérations d'E/S), il fait le travail. – perimosocordiae

14

Si le problème est ce que je pense qu'il est, votre problème est que IO Haskell est encadré: this question explique ce qui se passe. Lorsque vous exécutez un programme Haskell compilé, GHC stocke la sortie dans le tampon et ne l'envoie que périodiquement à l'écran; il le fait si (a) le tampon est trop plein, (b) si une nouvelle ligne est imprimée, ou (c) si vous appelez hFlush stdout.

L'autre problème que vous pouvez voir est que getChar peut ne pas se déclencher jusqu'à ce qu'une nouvelle ligne soit lue, mais alors le retour à la ligne est dans votre flux d'entrée; vous pourriez peut-être résoudre cela avec un getChar supplémentaire pour avaler la nouvelle ligne, mais il devrait probablement y avoir un meilleur moyen.

+0

Ouais, bon appel. Juste essayé moi-même; Fonctionne très bien dans GHCi, n'imprime rien jusqu'à la fin lorsqu'il est compilé, tout comme la question à laquelle vous êtes lié. –

6

Buffering, sous la forme de putStr, est votre problème, comme d'autres l'ont souligné.

En outre, un point de style: putStrLn $ show xs est le même que print xs