Here is minimal complete example:
import Control.Monad
import System.IO
loop :: IO ()
loop =
do line <- getLine
putStrLn line
eof <- isEOF
unless eof loop
main = loop
This program is supposed to read a line, print it out, stop if there is 'end of file' character in stdin. It doesn't leave the loop at all.
If I put eof <- isEOF before putStrLn line the program behaves very strange (try it!). I cannot get it at all: how putStrLn can possibly affect input stream and why doesn't the program terminate when I put 'end of file' character into stream (with Ctrl+D)?
Description of program's behavior when eof <- isEOF goes before putStrLn line:
After entering of a line, program does not print the entered line, but expects more input. As it gets more input, it starts to print previously entered lines. This is log of a test:
foo
boo
output: foo
bar
output: boo
baz
output: bar
< here I press Ctrl-D >
output: baz
Source:
import Control.Monad
import System.IO
loop :: IO ()
loop =
do line <- getLine
eof <- isEOF
putStrLn $ "output: " ++ line
unless eof loop
main =
do hSetBuffering stdin LineBuffering
loop