Sequencing of input and output, troubles in kdevelop
Hi, I used kdevelop to enter and compile the following code (Haskell): module Main where main = do putStr "naam invoerbestand?" inf <- getLine txt <- readFile inf putStr "naam uitvoerbestand?" outf <- getLine writeFile outf txt When executed I have to enter the first filename, then the second filename and finally the questions are both asked in one go and the program ends. This also happens if I executed the generated binary from an term. However, using hugs, I get the first question first, enter the filename, then I get the second question, I enter the filename and then the program ends. Why doesn't kdevelop generate code, that executes the statements in order? Or should I be looking at ghc? Or is it an option I am missing? Guus. -- A.J. Bonnema, Leiden The Netherlands, user #328198 (Linux Counter http://counter.li.org)
"A.J. Bonnema" <abonnema@xs4all.nl> writes:
Why doesn't kdevelop generate code, that executes the statements in order? Or should I be looking at ghc? Or is it an option I am missing?
GHCi behaves like Hugs. My guess would be that kdevelop attaches pipes for standard input and output, and GHC or whatever backend it uses realizes it is not talking to a terminal, and applies buffering. Note that the output is constant (i.e. always the two strings), so in a sense they can be output at any time without changing the meaning of the program. -kzm -- If I haven't seen further, it is by standing in the footprints of giants
"A.J. Bonnema" <abonnema@xs4all.nl> writes:
Why doesn't kdevelop generate code, that executes the statements in order? Or should I be looking at ghc? Or is it an option I am missing?
GHCi behaves like Hugs. My guess would be that kdevelop attaches pipes for standard input and output, and GHC or whatever backend it uses realizes it is not talking to a terminal, and applies buffering.
In other words - if kdevelop is supposed to support the use of interactive programs in its console window, it should allocate a pty, rather than just using ordinary Unix pipes. I would consider this a bug. The fix for now is for you to explicitly turn off buffering: import IO main = do hSetBuffering stdin LineBuffering hSetBuffering stdout NoBuffering hSetBuffering stderr NoBuffering ... (warning: untested code) --KW 8-) -- Keith Wansbrough <kw217@cl.cam.ac.uk> http://www.cl.cam.ac.uk/users/kw217/ University of Cambridge Computer Laboratory.
Ketil Malde wrote:
"A.J. Bonnema" <abonnema@xs4all.nl> writes:
Why doesn't kdevelop generate code, that executes the statements in order? Or should I be looking at ghc? Or is it an option I am missing?
GHCi behaves like Hugs. My guess would be that kdevelop attaches pipes for standard input and output, and GHC or whatever backend it uses realizes it is not talking to a terminal, and applies buffering.
Actually, I asked kdevelop to run in an external terminal. Also, if I run the command "./prog" (where prog is the name), the program behaves the same. So, ghc should not assume anything else than having input from standard input....
Note that the output is constant (i.e. always the two strings), so in a sense they can be output at any time without changing the meaning of the program.
I am not sure here. Isn't the output dependant on the input, because it depends on which filenames I enter? If I enter an erroneous input filename, the readFile should never be executed correctly. The same for the output filename. (I'll copy the code again for reference). module Main where main = do putStr "naam invoerbestand?" inf <- getLine txt <- readFile inf putStr "naam uitvoerbestand?" outf <- getLine writeFile outf txt Anyway, in my text on Haskell it says that IO creates a sort of imperative sublanguage within Haskell without compromising the rest of the modules. It uses a monad to do that. Now, I only just started learning, so I might well be wrong, but isn't the point about IO that statements *are* sequence dependent and there *are* side-effects? F.i. the effects of "x <- getChar; y <- getChar" may be different from "y <- getChar; x <- getChar", because there are side effects. So, sequence should be important. Well, as I said, I'm just starting...... Guus. -- A.J. Bonnema, Leiden The Netherlands, user #328198 (Linux Counter http://counter.li.org)
"A.J. Bonnema" <abonnema@xs4all.nl> writes:
Actually, I asked kdevelop to run in an external terminal. Also, if I run the command "./prog" (where prog is the name), the program behaves the same. So, ghc should not assume anything else than having input from standard input....
Hmm...did you try setting the buffering explicitly, as was suggested here?
I am not sure here. Isn't the output dependant on the input, because it depends on which filenames I enter? If I enter an erroneous input
Yes, that's true, a nonexisting file name should cause it to terminate before output is complete, I guess. It's slightly irrelevant, though, because the problem isn't the laziness in Haskell, but the laziness in the operating system in the form of buffering of output.
So, sequence should be important.
Yes. And as far as Haskell is concerned, it *has* pushed the string to stdout - but the OS delays the writing for performance reasons.
Well, as I said, I'm just starting......
Hope this helps, -kzm -- If I haven't seen further, it is by standing in the footprints of giants
On Fri, Aug 27, 2004 at 06:24:10PM +0200, Ketil Malde wrote:
Yes, that's true, a nonexisting file name should cause it to terminate before output is complete, I guess. It's slightly irrelevant, though, because the problem isn't the laziness in Haskell, but the laziness in the operating system in the form of buffering of output.
This kind of buffering is performed in user-space, and not by the operating system. In this case it is GHC's implementation of Handles. Most other language implementations also use this technique. Best regards, Tom -- .signature: Too many levels of symbolic links
Ketil Malde wrote:
"A.J. Bonnema" <abonnema@xs4all.nl> writes:
Actually, I asked kdevelop to run in an external terminal. Also, if I run the command "./prog" (where prog is the name), the program behaves the same. So, ghc should not assume anything else than having input from standard input....
Hmm...did you try setting the buffering explicitly, as was suggested here?
Sorry, I missed that suggestion. I just looked into kdevelop, and I couldn't find any buffering option. Also, ghc -help shows no buffering options (there is no man page for ghc). Do you know how to set buffering explicitely? Guus. -- A.J. Bonnema, Leiden The Netherlands, user #328198 (Linux Counter http://counter.li.org)
A.J. Bonnema wrote:
I used kdevelop to enter and compile the following code (Haskell):
module Main where
main = do putStr "naam invoerbestand?" inf <- getLine txt <- readFile inf putStr "naam uitvoerbestand?" outf <- getLine writeFile outf txt
When executed I have to enter the first filename, then the second filename and finally the questions are both asked in one go and the program ends. This also happens if I executed the generated binary from an term.
However, using hugs, I get the first question first, enter the filename, then I get the second question, I enter the filename and then the program ends.
Why doesn't kdevelop generate code, that executes the statements in order? Or should I be looking at ghc? Or is it an option I am missing?
As others have pointed out, the issue is the buffering. However, there is another issue which seems to have been overlooked: you aren't writing newlines, so the stream won't be flushed automatically even in the stream is line-buffered. If you use putStrLn instead of putStr, the stream will be flushed automatically (assuming that it is line-buffered, which is the default if the stream is associated with a terminal). If you don't want to add a newline, add explicit hFlush calls, i.e.: putStr "naam invoerbestand?" hFlush stdout inf <- getLine In C, you don't need to use fflush() in this situation because, when a read from a line-buffered input stream cannot be fulfilled from the buffer (i.e. the stdio code has to read() from the underlying descriptor), all line-buffered output streams are flushed automatically. The Haskell I/O library doesn't mimic this aspect of C, so you have to add explicit hFlush calls if you want partial lines (strings which don't end with a newline character) to be displayed immediately. -- Glynn Clements <glynn.clements@virgin.net>
participants (5)
-
A.J. Bonnema -
Glynn Clements -
Keith Wansbrough -
Ketil Malde -
Tomasz Zielonka