15

A friend of mine asked me why was I learning Haskell. To demonstrate the power of Haskell I wrote a small program which displayed a list of prime numbers:

main = do putStr "Enter the number of prime numbers to display: " number <- fmap read getLine :: IO Int print . take number . filter isPrime $ [2..] isPrime :: Integer -> Bool isPrime n = not . any ((== 0) . mod n) $ [2..floor . sqrt . fromInteger $ n] 

The program works as expected save a minor anomaly. It prints the prompt message after taking an input number from the user resulting in an output like:

12 Enter the number of prime numbers to display: [2,3,5,7,11,13,17,19,23,29,31,37] 

Why is Haskell not sequencing the IO actions correctly? Where am I going wrong?

2 Answers 2

25

This looks more like a buffering than a sequencing problem. What platform are you on? Have you tried forcing unbuffered output?

hSetBuffering stdout NoBuffering -- from System.IO 
Sign up to request clarification or add additional context in comments.

5 Comments

I'm using the Glasgow Haskell Compiler. Thank you. That was indeed the problem. I need to learn more about IO operations in Haskell.
By platform I meant more like OS and terminal. Usually, stdin and stdout are "tied" in a way that makes stdout flush whenever stdin is read from, precisely to avoid that sort of problem. FWIW, your problem both buffers and sequences properly on my setup.
Oh, I'm using the "Terminal" on Ubuntu 13.10. I'm not really sure whether it has a specific name like xterm but it's the same terminal found on a Macintosh OSX.
Edit: I have the same "untied" behavior using Debian and LXTerminal or gnome-terminal. The C people seem to agree that there isn't an automatic flush
The tie thing is more of a C++ thing. I can't seem to find an authoritative mention of this about Haskell of GHC, so it's reasonable to assume there's no such thing here either. My setup (GHCi in emacs) is ultra-biased.
11

stdin and stdout are two different files that needn't have any connection. Take e.g. the Unix shell command grep:

$ seq 1 100 | grep 2$ | less 

seq 1 100 prints the numbers 1 to 100 to its stdout which is greps stdin (| connects the stdout of one command to the stdin of an other). grep then writes the lines that match the given regex to its stdout which is lesss stdin.

To force stdout (or any other file) to be written use hFlush from System.IO:

 hFlush stdout 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.