Search code examples
haskelllazy-evaluation

How to make certain IO operations in Haskell strict?


I want to write a Haskell program that outputs a prompt and accepts user input on the same line that the prompt was outputted to. In order to do this I believe I need to force evaluation of the function putStr.

echoWithPrompt :: IO ()
echoWithPrompt = do
                  putStr "input: "
                  echo <- getLine :: IO String
                  putStrLn echo


main :: IO ()
main = do
        echoWithPrompt

Running this as is will not print "input: " until after the user has inputted a line. I have tried things like

write <- putStr "input: "
echo <- write `deepseq` getLine :: IO String

or

putStr $! "input: "

to try to force the message to print but to no avail.


Solution

  • That is only due to flushing. It has nothing to do with laziness. You can flush the stdout with:

    import System.IO(hFlush, stdout)
    
    echoWithPrompt :: IO ()
    echoWithPrompt = do
        putStr "input: "
        hFlush stdout
        echo <- getLine
        putStrLn echo

    or shorter:

    import System.IO(hFlush, stdout)
    
    echoWithPrompt :: IO ()
    echoWithPrompt = putStr "input: " >> hFlush stdout >> getLine >>= putStrLn