Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

putStr and putStrLn messing with the output [duplicate]

Tags:

io

haskell

I was learning haskell from Learn You a Haskell For Great Good book. There was this code

import Control.Monad
import Data.Char
main = forever $ do
    putStr "Give me some input: "
    l <- getLine
    putStrLn $ map toUpper l

when i am running this code in gitbash at first it is just asking for any input after giving the input text and hitting enter( say the input text was soham) it is showing Give me some input: SOHAM.

enter image description here

Then i changed the code to

import Control.Monad
import Data.Char
main = forever $ do
    putStrLn "Give me some input: "
    l <- getLine
    putStrLn $ map toUpper l

and after running it is showing me Give me some input: and asking for an input. after giving the same input soham it is showing SOHAM

enter image description here

Again changing the code to

import Control.Monad
import Data.Char
main = forever $ do
    putStr "Give me some input: "
    l <- getLine
    putStr $ map toUpper l

It is just taking input again and again and when i am pressing the end of file key(ctrl+C) it is showing all the output one after another side by side but the out puts are like the original code.

enter image description here

Why such variations are happening ?

like image 975
Soham Chatterjee Avatar asked Sep 20 '25 00:09

Soham Chatterjee


1 Answers

This is likely due to buffering: with LineBuffering it will flush in whenever a new line is output. This thus means that if you use putStr, and the string itself does not contain a new line '\n' character, it will buffer the ouput and wait until a new line is written to actually write the output to the console

You can set it to NoBuffering to write the content immediately to the console. You can change the buffering settings for the stdout with hSetBuffering :: Handle -> BufferMode -> IO ():

import Control.Monad
import Data.Char
import System.IO

main = do
  hSetBuffering stdout NoBuffering
  forever $ do
    putStr "Give me some input: "
    l <- getLine
    putStrLn $ map toUpper l

another option is to flush the buffer only for putStr with hFlush :: Handle -> IO (), and thus not change the buffering policy itself:

import Control.Monad
import Data.Char
import System.IO

main = do $ forever
  putStr "Give me some input: "
  hFlush stdout
  l <- getLine
  putStrLn $ map toUpper l
like image 145
Willem Van Onsem Avatar answered Sep 23 '25 02:09

Willem Van Onsem