Skip to main content

Exceptions

What happens if the file does not exist?

GHCi> readFileLineByLine "doesnotexist"
*** Exception: doesnotexist: openFile: does not exit
(No such file or directory)

Exceptions in effectful vs effect-free code

Exceptions in pure code (via error , missing patterns, ...) are bad:

  • It is unclear when exactly, or if, they will be triggered,
  • It is therefore also unclear where or when to best handle them,
  • Explicitly handling failure via Maybe or similar is almost always the better solution.

Exceptions in effectful ( IO ) code are different:

  • Execution order is explicit, and handling is easier.
  • There are many things that go wrong.

Catching IO errors

From System.IO.Error :
catchIOError :: IO a -> (IOError -> IO a) -> IO a
readFileLineByLine' ::
FilePath -> IO (Maybe [String])
readFileLineByLine' file =
catchIOError
(liftM Just (readFileLineByLine file))
(const (return Nothing))

Testing it

GHCi> writeFile "test" "foo\nbar"
GHCi> readFileLineByLine' "test"
Just ["foo", "bar"]
GHCi> removeFile "test"
GHCi> readFileLineByLine' "test"
Nothing

From System.Directory :

removeFile :: FilePath -> IO ()

Recap

  • The role of the IO type.
  • Composing IO functions.
  • Higher-order IO functions ( sequence , mapM ).
  • File IO.
  • Resources.
  • Exceptions.