Hello all. I'm new to functional programming and Haskell, but have been programming in C and Java for a while. I've been going through the tutorials and whatnot on haskell.org. I've read from the Gentle Introduction to Haskell about IO and some of the other stuff and I have a question about it. main = do putStr "Type Something: " str <- getLine putStrLn ("You typed: " ++ str) When compile and run this code the "Type Something: " isn't displayed until the putStrLn. So there is no prompt. The output looks like this. s Type Something: You typed: s But if I change the putStr "Type Something: " to a putStrLn or put a \n at the end of the string it displays the text immediately (ie, when I want it to). Is there a good reason for this? Am I doing something wrong? Or do I need to call some kind of standard output flush? Thanks. Oh, I'm using ghc. Matt -- "Not everone knows Josiah Royce's definition of a liar as a man who willfully misplaces his ontological predicates, but everyone who has ever told a lie will recognize its accuracy." Ch. 94: Truth - "The Great Ideas: A Synopticon of Great Books of the Western World"
On Fri, 12 Sep 2003 16:27:59 -0600 Matt O'Connor <angagon@earthlink.net> wrote:
Hello all. I'm new to functional programming and Haskell, but have been programming in C and Java for a while. I've been going through the tutorials and whatnot on haskell.org. I've read from the Gentle Introduction to Haskell about IO and some of the other stuff and I have a question about it.
main = do putStr "Type Something: " str <- getLine putStrLn ("You typed: " ++ str)
When compile and run this code the "Type Something: " isn't displayed until the putStrLn. So there is no prompt. The output looks like this.
s Type Something: You typed: s
But if I change the putStr "Type Something: " to a putStrLn or put a \n at the end of the string it displays the text immediately (ie, when I want it to). Is there a good reason for this? Am I doing something wrong? Or do I need to call some kind of standard output flush?
Yes, the problem is that the first line is not being flushed. Importing hFlush and stdout from IO (or System.IO) and adding hFlush stdout after you putStr will fix it. Alternatively, you could change the buffering on stdout to NoBuffering. I don't know if there is a standard putStrWithFlush function or just a better answer than this. A putStrWithFlush would be trivial to write or more generally to a HOF that flushed after performing the action passed to it.
This is a buffering problem. Use hSetBuffering to fix this (see Chapter 3 in YAHT -- www.isi.edu/~hdaume/htut/). Alternatively, use:
main = do putStrLn "Type Something:" ...
in which case the "Ln" part will force it to be printed. - Hal On Fri, 12 Sep 2003, Matt O'Connor wrote:
Hello all. I'm new to functional programming and Haskell, but have been programming in C and Java for a while. I've been going through the tutorials and whatnot on haskell.org. I've read from the Gentle Introduction to Haskell about IO and some of the other stuff and I have a question about it.
main = do putStr "Type Something: " str <- getLine putStrLn ("You typed: " ++ str)
When compile and run this code the "Type Something: " isn't displayed until the putStrLn. So there is no prompt. The output looks like this.
s Type Something: You typed: s
But if I change the putStr "Type Something: " to a putStrLn or put a \n at the end of the string it displays the text immediately (ie, when I want it to). Is there a good reason for this? Am I doing something wrong? Or do I need to call some kind of standard output flush? Thanks.
Oh, I'm using ghc.
Matt
-- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
Hal was pretty terse, so I'll explain why switching to putStrLn will help. stdout is line buffered. At least by default (see hSetBuffering). That means output will only be flushed to the screen once a newline is written. Your prompt wasn't printed because it didn't have a newline, so it was buffered until the second print provided one (read from the user, by way of s). This is hardly specific to Haskell. Try this C program: #import <stdio.h> #import <unistd.h> int main(int a,char** b) { fputs("test",stdout); sleep(1); fputs("boo!\n",stdout); return 0; } on my system this sleeps a second then prints "testboo!". I used fputs rather than puts becuase puts appends a newline and fputs doesn't. Similarly, putStrLn appends a newline and putStr doesn't. This change does mean input will be entered on the next line, rather then on the same line as the prompt. This should be acceptable. If you really need to have a prompt at the start of the line then consider hFlush or hSetBuffering. Every time I've seen this question asked people post responses that only mention hFlush, implying you need it to display output when you want it. Please don't give newbies the impression you need hFlush for basic IO. Monadic IO is scary enough to begin with. This seems to be a common problem so I added some comments about it on the Wiki, under UsingIO in the FrequentlyAskedQuestions. Brandon On Fri, 12 Sep 2003, Hal Daume III wrote:
This is a buffering problem. Use hSetBuffering to fix this (see Chapter 3 in YAHT -- www.isi.edu/~hdaume/htut/). Alternatively, use:
main = do putStrLn "Type Something:" ...
in which case the "Ln" part will force it to be printed.
- Hal
On Fri, 12 Sep 2003, Matt O'Connor wrote:
Hello all. I'm new to functional programming and Haskell, but have been programming in C and Java for a while. I've been going through the tutorials and whatnot on haskell.org. I've read from the Gentle Introduction to Haskell about IO and some of the other stuff and I have a question about it.
main = do putStr "Type Something: " str <- getLine putStrLn ("You typed: " ++ str)
When compile and run this code the "Type Something: " isn't displayed until the putStrLn. So there is no prompt. The output looks like this.
s Type Something: You typed: s
But if I change the putStr "Type Something: " to a putStrLn or put a \n at the end of the string it displays the text immediately (ie, when I want it to). Is there a good reason for this? Am I doing something wrong? Or do I need to call some kind of standard output flush? Thanks.
Oh, I'm using ghc.
Matt
-- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Brandon Michael Moore wrote:
Hal was pretty terse, so I'll explain why switching to putStrLn will help.
stdout is line buffered.
At least by default (see hSetBuffering). That means output will only be flushed to the screen once a newline is written. Your prompt wasn't printed because it didn't have a newline, so it was buffered until the second print provided one (read from the user, by way of s).
This is hardly specific to Haskell. Try this C program:
But there's one significant difference between C and Haskell, which is applicable in the case of Matt's program. In C, any line-buffered output streams are automatically flushed when a read from an unbuffered or line-buffered stream can't be satisfied from its buffer. Also, it seemed fairly clear from Matt's original message that: a) he didn't want to have to force a new-line (he noted that doing so eliminated the problem), and b) he understood the concept of flushing, but presumably didn't know how to do it in Haskell. While we're on the subject, I'll point out a couple of other differences between the buffering in ANSI C's stdio library and Haskell's: 1. In Haskell, you can change the buffering mode at any point; in C, you have to change it before any data is read from or written to the stream, otherwise the behaviour is undefined. 2. For an input stream which is associated with a tty, changing the buffering mode may also change the terminal settings (setting it to unbuffered disables canonical mode while setting it to line-buffered or fully-buffered enables it). -- Glynn Clements <glynn.clements@virgin.net>
On Sun, 14 Sep 2003, Glynn Clements wrote:
Brandon Michael Moore wrote:
Hal was pretty terse, so I'll explain why switching to putStrLn will help.
stdout is line buffered.
At least by default (see hSetBuffering). That means output will only be flushed to the screen once a newline is written. Your prompt wasn't printed because it didn't have a newline, so it was buffered until the second print provided one (read from the user, by way of s).
This is hardly specific to Haskell. Try this C program:
But there's one significant difference between C and Haskell, which is applicable in the case of Matt's program. In C, any line-buffered output streams are automatically flushed when a read from an unbuffered or line-buffered stream can't be satisfied from its buffer.
Interesting. I didn't know this. Maybe we should match this behaviour, or provide a write-string-and-flush function. It seems like this issue is causing an undue amound of trouble.
Also, it seemed fairly clear from Matt's original message that:
a) he didn't want to have to force a new-line (he noted that doing so eliminated the problem), and
I should note here that there is a gnu readline binding distributed with GHC. It's undocumented, but it seems to follow the C API pretty closely, and you can make a decent interface using only two of the functions.
b) he understood the concept of flushing, but presumably didn't know how to do it in Haskell.
While we're on the subject, I'll point out a couple of other differences between the buffering in ANSI C's stdio library and Haskell's:
1. In Haskell, you can change the buffering mode at any point; in C, you have to change it before any data is read from or written to the stream, otherwise the behaviour is undefined.
2. For an input stream which is associated with a tty, changing the buffering mode may also change the terminal settings (setting it to unbuffered disables canonical mode while setting it to line-buffered or fully-buffered enables it).
-- Glynn Clements <glynn.clements@virgin.net> _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Matt O'Connor wrote:
Hello all. I'm new to functional programming and Haskell, but have been programming in C and Java for a while. I've been going through the tutorials and whatnot on haskell.org. I've read from the Gentle Introduction to Haskell about IO and some of the other stuff and I have a question about it.
main = do putStr "Type Something: " str <- getLine putStrLn ("You typed: " ++ str)
When compile and run this code the "Type Something: " isn't displayed until the putStrLn. So there is no prompt. The output looks like this.
s Type Something: You typed: s
But if I change the putStr "Type Something: " to a putStrLn or put a \n at the end of the string it displays the text immediately (ie, when I want it to). Is there a good reason for this? Am I doing something wrong? Or do I need to call some kind of standard output flush? Thanks.
Yes; if you don't want a newline after the prompt, you need to use: hFlush stdout to flush the stream. -- Glynn Clements <glynn.clements@virgin.net>
participants (5)
-
Brandon Michael Moore -
Derek Elkins -
Glynn Clements -
Hal Daume III -
Matt O'Connor