[Haskell-cafe] Re: Silly I/O question

Peter Simons simons at cryp.to
Tue Sep 28 17:06:30 EDT 2004

John Goerzen writes:

 > That failed, though, because getContents closes the file
 > after it's been completely read (ugh -- why?).

getContents reads from standard input: you can't seek on
that stream. Just think of "cat <file | cat". The second
invocation reads from a pipe, not from a file on disk.

To accomplish your goal, you could read the file _once_ with
getContents, and just print it multiple times, like this:

  printTimes  :: Int -> String -> IO ()
  printTimes  n msg = sequence_ (replicate n (putStr msg))

  printTimes' :: Int -> String -> IO ()
  printTimes' n msg = putStr (concat (replicate n msg))

This means, unfortunately, that you'll have to keep the
whole file in memory, but if you want to read from standard
input, there is no way around that.

You could read the contents once, write it to a temporary
file, and then copy it multiple times from there. Then you
could do it in blocks. But that's probably not what you want
to do.

 > But I couldn't figure out a way to make this either
 > properly tail-recursive while handling the exception, or
 > to avoid polling for EOF each time through the function.

You might want to write a function that copies the file
_once_ and then just call that function several times. Like
in the examples above. I don't think you need explicit
recursion at all.

Hope this is helpful.


More information about the Haskell-Cafe mailing list