flushing stdout

20 views
Skip to first unread message

Alex M

unread,
Nov 17, 2011, 2:02:43 AM11/17/11
to stanford-1...@googlegroups.com
I'm having trouble doing some basic putStr's on stdout. All I want to do is print a line to stdout and then wait on user input on stdin. However, doing this:

putStr "Enter query:\n"
query <- getLine

doesn't print "Enter query" until the user presses Enter. I tried:

putStr "Enter query:\n"
hFlush stdout
query <- getLine

Where am I going wrong?

Eugene Perederey

unread,
Nov 17, 2011, 2:12:48 AM11/17/11
to Stanford CS240h 2011 Autumn
Works for me:
main = do
putStr "Enter query:\n"
query <- getLine
return ()

can you show the entire do block?

Alex M

unread,
Nov 17, 2011, 4:53:22 AM11/17/11
to stanford-1...@googlegroups.com
my code actually looks more like this

main = do
  eof <- hIsEOF stdin
  if eof then return () else do
                          putStr "Enter query:\n"
                          query <- hGetLine stdin
                          return ()

Alex M

unread,
Nov 17, 2011, 4:55:44 AM11/17/11
to stanford-1...@googlegroups.com
actually, you can even get rid of all the h's:

main = do
  eof <- isEOF
  if eof then return () else do
                          putStr "Enter query:\n"
                          query <- getLine
                          return ()

Eugene Perederey

unread,
Nov 17, 2011, 5:36:23 AM11/17/11
to Stanford CS240h 2011 Autumn
I think isEOF just blocks waiting for the input, and when user gives
an input it is consumed by getLine.
Maybe it's more appropriate to use try or catch to handle getLine
failure?

Alex M

unread,
Nov 17, 2011, 5:39:58 AM11/17/11
to stanford-1...@googlegroups.com
Yea I'm not sure what the accepted idiom is for reading until end of file.

Herbert Valerio Riedel

unread,
Nov 17, 2011, 6:03:32 AM11/17/11
to stanford-1...@googlegroups.com
On Wed, 2011-11-16 at 23:02 -0800, Alex M wrote:
>
> putStr "Enter query:\n"

btw, why don't you use 'putStrLn' instead? I.e.

putStrLn "Enter query:"

Bryan O'Sullivan

unread,
Nov 17, 2011, 1:24:09 PM11/17/11
to stanford-1...@googlegroups.com
On Thu, Nov 17, 2011 at 2:36 AM, Eugene Perederey <eugene.p...@gmail.com> wrote:
I think isEOF just blocks waiting for the input, and when user gives
an input it is consumed by getLine.
Maybe it's more appropriate to use try or catch to handle getLine
failure?

That's correct.

I don't like that "EOF is an exceptional condition" API design, but it's what we're stuck with.

Alex M

unread,
Nov 18, 2011, 9:44:45 PM11/18/11
to stanford-1...@googlegroups.com
On Thu, Nov 17, 2011 at 2:36 AM, Eugene Perederey
<eugene.p...@gmail.com> wrote:
> I think isEOF just blocks waiting for the input, and when user gives
> an input it is consumed by getLine.

What exactly does it mean for isEOF to "block" waiting for input? It's
a single threaded program, so I thought isEOF just checks a flag or a
bit somewhere and then the rest of the IO monad gets executed. So it's
still not clear to me why stuff isn't getting flushed to stdout.

Eugene Perederey

unread,
Nov 18, 2011, 9:51:05 PM11/18/11
to Stanford CS240h 2011 Autumn
I don't know how exactly it is implemented but my impression was that
isEOF is polling stdin until something appears in it.

On Nov 18, 6:44 pm, Alex M <amord...@gmail.com> wrote:
> On Thu, Nov 17, 2011 at 2:36 AM, Eugene Perederey
>

Alex M

unread,
Nov 19, 2011, 4:27:27 AM11/19/11
to stanford-1...@googlegroups.com
Thus preventing anything from being printed to stdout? That seems like
a very strange way to implement IO. Perhaps one of the instructors
could comment on this.

Alex M

unread,
Nov 23, 2011, 5:47:31 PM11/23/11
to stanford-1...@googlegroups.com
Could an instructor please comment on this?

Eugene Perederey

unread,
Nov 23, 2011, 7:26:14 PM11/23/11
to Stanford CS240h 2011 Autumn
While waiting for instructors' response, let me comment on this.
I honestly don't see anything weird here.
Here in IO monad you have two actions:
eof <- hIsEOF stdin
and
if eof then ... else ...
and the second one depends on the first one.
Thus it cannot be computed until eof is ready.

Drew Haven

unread,
Nov 23, 2011, 8:17:49 PM11/23/11
to stanford-1...@googlegroups.com
If it's not reading a file, hIsEOF blocks because it wants to read at least one character.  See the docs and the source.  I think the issue is that stdin is an open stream, so it can't just check if it is at the end without trying to read one more character.  I think you're best off catching the error and dealing with it appropriately. 

David Terei

unread,
Nov 23, 2011, 8:53:14 PM11/23/11
to stanford-1...@googlegroups.com
So Drew is right.

Stdin is a stream, talking about EOF is a little strange at times. Try
this, run your program and type CTRL-D. Your program will run taking
the true case. Given stdin is a stream the question of 'are we are the
eof?' can't be answered until the user types in some input. Maybe they
type 'c' and we can say no its not the eof, maybe they type CTRL-D and
we say yes it is the end of file.

If you want to do a lot of user interaction then perhaps using the
Haskel version of readline would be the best approach:

http://hackage.haskell.org/package/haskeline-0.6.4.5

Cheers,
David

dm-list-clas...@scs.stanford.edu

unread,
Nov 24, 2011, 3:09:13 PM11/24/11
to stanford-1...@googlegroups.com
At Wed, 23 Nov 2011 17:47:31 -0500,

Alex M wrote:
>
> Could an instructor please comment on this?

What exactly is the question?

hIsEOF returns True if you are at EOF. To do that, it may have to
wait for more input. For example, if your handle is attached to a TCP
socket and there is no data buffered, then hIsEOF will block until the
TCP stack receives either a data segment or a FIN segment. The
behavior for pipes Unix domain sockets, and terminals is similar--it
will block until the other end of the connection has done something to
distinguish an EOF condition from a non-EOF condition.

David

Reply all
Reply to author
Forward
0 new messages