
Hi !, I have the following program from “Learn You a Haskell” ( http://learnyouahaskell.com/input-and-output#randomness ). When i run this using runhaskell, code works perfectly fine. However, when i compile and run the binary file, code behaves differently. Basically, in the following code, we print a line first and the read the line from stdin. This behavior works perfectly fine when using “runhaskell guess.hs”. But when i say “./guess”, i had to type in a number directly ( i.e. first prompt is skipped ). btw.. i am using mac yosomite command terminal. Any help greatly appreciated.. Thanks a lot in advance.. import System.Random import Control.Monad(when) main = do ranGen <- getStdGen let (rand,_) = randomR (1,10) ranGen :: (Int,StdGen) putStr "Guess a number between 1 and 10 : " numStr <- getLine when(not $ null numStr) $ do let num = read numStr if rand == num then putStrLn "Yuhaa!! you are right baby!" else putStrLn $ "Sorry dude!! it was " ++ show rand newStdGen main

On Tue, Feb 3, 2015 at 10:23 PM, Madhu Babu
Basically, in the following code, we print a line first and the read the line from stdin. This behavior works perfectly fine when using “runhaskell guess.hs”. But when i say “./guess”, i had to type in a number directly ( i.e. first prompt is skipped ).
runhaskell is presumably using unbuffered I/O for some reason, so outputting directly to the terminal. The compiled program follows standard Unix buffering conventions: line buffering on output to a terminal, so the putStr is sitting in a buffer waiting to see a newline output. C / C++ programs also do buffering, but there's a heinous hack which detects reads on stdin and flushes stdout beforehand. (Heinous because there is no guarantee that they are actually related --- but naïve programmers invariably do not learn about line buffering and expect all output to be unbuffered(*), and C standard library programmers eventually gave up and catered to them after years of trying to get them to pay attention. I have a nasty suspicion we're going to end up with a similar horrible hack in Haskell eventually.) You can use hFlush from System.IO to flush the prompt out to the terminal, or disable output buffering with hSetBuffering in the same module. (*) At some point someone will pop up and say that on modern computers, buffering is obsolete because it's fast enough that horribly inefficient character-at-a-time I/O is good enough. Yet, I can *still* see visible hesitations when character-at-a-time I/O is used on a modern Intel core i5/i7. And your disk benchmarks will *tank* even with server-class disk subsystems. -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

Hey Madhu,
Right, this is another gotcha -- haskell has a bunch of them.
As Tristan and Brandon have remarked, the runhaskell interpreter and
compiled programs handle output buffering differently.
Here are changes to make your game work:
On Wed, Feb 4, 2015 at 10:23 AM, Madhu Babu
import System.Random import Control.Monad(when)
import System.IO
main = do ranGen <- getStdGen let (rand,_) = randomR (1,10) ranGen :: (Int,StdGen)
hSetBuffering stdout NoBuffering
putStr "Guess a number between 1 and 10 : "
You might want to take a look at the "Summing Two Numbers" section here: https://www.haskell.org/onlinereport/io.html -- Kim-Ee
participants (3)
-
Brandon Allbery
-
Kim-Ee Yeoh
-
Madhu Babu