[Haskell-cafe] Re: Silly I/O question
Jon Fairbairn
Jon.Fairbairn at cl.cam.ac.uk
Tue Sep 28 17:59:58 EDT 2004
On 2004-09-28 at 21:19-0000 John Goerzen wrote:
> On 2004-09-28, Peter Simons <simons at cryp.to> wrote:
> > John Goerzen writes:
> FWIW, this is working for me:
>
> import IO
>
> main = disp 100
>
> disp 0 = return ()
> disp n =
> let copy x = do
> eof <- isEOF
> if eof
> then return ()
> else do
> line <- getLine
> putStrLn line
> (copy 0)
> in do
> copy 0
> hSeek stdin AbsoluteSeek 0
> disp (n-1)
>
> but it seems wasteful to poll isEOF so much.
Why do you say that? The condition has to be tested for,
whether you do it by polling or waiting for an error to be
thrown
For my 2¢, I think I prefere this sort of thing to look like
this:
> import IO
>
>
> number_of_copies = 100
>
> main = mapM_ contentsToStdOut $ replicate number_of_copies stdin
>
> contentsToStdOut hdl
> = do line_by_line hdl
> hSeek hdl AbsoluteSeek 0
>
>
> line_by_line hdl = foldIO (const putStrLn) () hGetLine hdl
>
> foldIO process_item initial_state io_operation handle
> = process initial_state
> where process state
> = do eof <- hIsEOF handle
> if eof
> then return state
> else do item <- io_operation handle
> new_item <- process_item state item
> process $ new_item
and some version of foldIO should probably be in a library
somewhere.
If you really don't like polling, you can write this:
> contentsToStdOut hdl
> = do t <- try $ line_by_line hdl
> hSeek hdl AbsoluteSeek 0
> case t of
> Right () -> error "this never happens"
> Left e -> if isEOFError e
> then return ()
> else ioError e
with
> line_by_line hdl
> = do line <- hGetLine hdl
> putStrLn line
> line_by_line hdl
Note that all of these are incorrect because hGetLine
doesn't tell you whether there was a newline at the end of
file.
--
Jón Fairbairn Jon.Fairbairn at cl.cam.ac.uk
More information about the Haskell-Cafe
mailing list