+13
Haskell/exceptions.org
+13
Haskell/exceptions.org
···
1
+
* Exceptions
2
+
3
+
Pure functions are lazy by default, which means that we don't know when they will be evaluated and that it really shouldn't matter.
4
+
However, once pure functions start throwing exceptions, it matters when they are evaluated.
5
+
That's why we can only catch exceptions thrown from pure functions in the I/O part of our code.
6
+
And that's bad because we want to keep the I/O part as small as possible.
7
+
However, if we don't catch them in the I/O part of our code, our program crashes.
8
+
The solution? Don't mix exceptions and pure code.
9
+
Take advantage of Haskell's powerful type system and use types like *Either* and *Maybe* to represent results that may have failed.
10
+
11
+
Let's make an example using *catch* to treat errors when opening a file that does not exists.
12
+
13
+
[[file:files/countLinesException.hs][Example of exception handling]]
+18
Haskell/files/countLinesException.hs
+18
Haskell/files/countLinesException.hs
···
1
+
import System.Environment
2
+
import System.IO.Error
3
+
import Control.Exception
4
+
5
+
main = toTry `catch` handler
6
+
7
+
toTry :: IO ()
8
+
toTry = do (fileName:_) <- getArgs
9
+
contents <- readFile fileName
10
+
putStrLn $ "The file has " ++ (show $ length $ lines contents) ++ " lines!"
11
+
12
+
handler :: IOError -> IO ()
13
+
handler e
14
+
| isDoesNotExistError e =
15
+
case ioeGetFileName e of Just name -> putStrLn ("Whoops! File does not exist at: " ++ name)
16
+
Nothing -> putStrLn "Whoops! File does not exist at unknown location!"
17
+
| otherwise = ioError e
18
+