IO pasa fuera de servicio al usar getLine y putStr

Soy un principiante de Haskell, estoy empezando a entender a las Mónadas, pero todavía no lo entiendo. Estoy escribiendo un juego que consiste en pedirle al usuario su opinión y responderle. Aquí hay una versión simplificada de mi función:

getPoint :: IO Point getPoint = do putStr "Enter x: " xStr <- getLine putStr "Enter y: " yStr  IO (Board, Player) completeUserTurn (board, player) = do putStr $ "Enter some value: " var1 <- getLine putStr $ "Enter another value: " var2 <- getLine putStr $ "Enter a point this time: " point <- getPoint if (... the player entered legal values ...) then do putStr $ "This is what would happen if you did that: {stuff} do you want to do that? (y/n) " continue <- getLine if continue == "y" then return (...updated board..., ...updated player...) else completeUserTurn (board, player) else do putStr "Invalid Move!\n" completeUserTurn (board, player) 

Lo que sucede es que las indicaciones aparecerán desordenadas con el texto que se supone que debe aparecer antes del aviso.

Aquí hay un ejemplo de lo que sucede después de que compilé el código anterior:

1
Ingrese un valor: ingrese otro valor: 2
3
4
Ingrese un punto esta vez: Ingrese x: Ingrese y: y
¿Es esto correcto? (y / n):

Las negritas son las cosas que escribí

Obviamente, tengo un gran error conceptual, pero no sé qué. Tenga en cuenta que funciona correctamente en el intérprete y falla cuando se comstack.

Como dijo Michael, el problema es amortiguar. De forma predeterminada, la salida se almacena en búfer hasta que imprima una línea nueva (o hasta que el búfer esté lleno si tiene líneas realmente largas), por lo que con mayor frecuencia verá este problema cuando intente hacer indicaciones de la misma línea usando putStr como lo hace .

Sugiero que defina una pequeña función auxiliar como esta para que se encargue de enjuagarla por usted:

 import System.IO prompt :: String -> IO String prompt text = do putStr text hFlush stdout getLine 

Ahora puedes simplemente hacer

 getPoint = do xStr <- prompt "Enter x: " yStr <- prompt "Enter y: " return $ Point (read xStr) (read yStr) 

El IO está sucediendo en el orden correcto. El problema es el almacenamiento en búfer. Si vacía stdout después de cada putStr, debería funcionar como esperaba. Tendrá que importar hFlush y stdout desde System.IO .

El problema no estaba en el orden de las operaciones en el código IO. El problema fue la entrada y la salida se almacenó de forma predeterminada al usar stdin y stdout. Esto aumenta el rendimiento de IO en una aplicación, pero puede hacer que las operaciones parezcan estar fuera de servicio cuando se usan stdin y stdout.

Hay dos soluciones para esto. Puede utilizar el método hFlush para forzar un identificador (ya sea stdin o stdout) para que se vacíe. hFlush stdout , hFlush stdin . Una solución más simple (que funciona bien para aplicaciones interactivas) es deshabilitar el almacenamiento en búfer por completo. Puede hacer esto llamando a los métodos hSetBuffering stdout NoBuffering y hSetBuffering stdin NoBuffering antes de iniciar su progtwig (es decir, ponga esas líneas en su método principal.

    Intereting Posts