Detecting I/O exceptions in a lazy String from hGetContents?

error-handling, haskell

Solution

Lazy IO is considered to be a pitfall by many haskellers and as such is advised to keep away from. Your case colorfully describes why.

There is a non-lazy alternative of `hGetContents` function. It works on `Text`, but `Text` is also a generally preferred alternative to `String`. For convenience, there are modern preludes, replacing the `String` with `Text`: basic-prelude and classy-prelude.

Problem

hGetContents returns a lazy String object that can be used in purely functional code to read from a file handle. If an I/O exception occurs while reading this lazy string, the underlying file handle is closed silently and no additional characters are added to the lazy string. How can this I/O exception be detected? As a concrete example, consider the following program: ``` import System.IO -- for stdin lengthOfFirstLine :: String -> Int lengthOfFirstLine "" = 0 lengthOfFirstLine s = (length . head . lines) s main :: IO () main = do lazyStdin <- hGetContents stdin print (lengthOfFirstLine lazyStdin) ``` If an exception occurs while reading the first line of the file, this program will print the number of characters until the I/O exception occurs. Instead I want the program to crash with the appropriate I/O exception. How could this program be modified to have that behavior? Edit: Upon closer inspection of the hGetContents implementation, it appears that the I/O exception is not ignored but rather bubbles up through the calling pure functional code to whatever IO code happened to trigger evaluation, which has the opportunity to then handle it. (I was not previously aware that pure functional code could raise exceptions.) Thus this question is a misunderstanding. Aside: It would be best if this exceptional behavior were verified empirically. Unfortunately it is difficult to simulate a low level I/O error.

Original source

Related problems