Haskell Pure Errors versus IO Exceptions
Haskell pure errors and IO exceptions are two different kinds of failure. Pure errors are values like Maybe and Either, while IO exceptions are runtime failures from IO actions.
A pure error is just a value
The Left value prints like any other value. The program then prints its next line.
main :: IO ()
main = do
print (Left "bad input" :: Either String Int)
putStrLn "still running"A caught IO failure lets the program continue
The missing file is caught by try. The program then prints its next line.
import Control.Exception (try, IOException, evaluate)
main :: IO ()
main = do
r <- try (do t <- readFile "no-such-pure.txt"; _ <- evaluate (length t); return t) :: IO (Either IOException String)
putStrLn (case r of Left _ -> "caught"; Right _ -> "found")
putStrLn "still running"Pure Either needs a case, not try
The pure function returns Left for a negative input and Right for 5. No try is used, because no exception exists.
check :: Int -> Either String Int
check n = if n < 0 then Left "negative" else Right n
main :: IO ()
main = do
print (check (-3), check 5)Example
import Control.Exception (try, IOException, evaluate)
checkAge :: Int -> Either String Int
checkAge a = if a < 0 then Left "too young" else Right a
main :: IO ()
main = do
print (checkAge (-1))
case checkAge 30 of
Left e -> putStrLn e
Right age -> do
writeFile "pure-io.txt" (show age)
txt <- readFile "pure-io.txt"
putStrLn txt
r <- try (do t <- readFile "no-such-pure2.txt"; _ <- evaluate (length t); return t) :: IO (Either IOException String)
putStrLn (case r of Left _ -> "caught"; Right _ -> "found")Key points
- Pure error: a pure error is an ordinary value returned by a pure function.
- IO exception: an IO exception is a runtime failure raised by an IO action.
- Try and catch: try and catch handle IO exceptions, not pure values.
- Case: a program handles a pure Either value with a case or a fold.
- Continue: both kinds can be handled so the program keeps running.
In this example, the program prints a pure Left value for a bad age. It then uses a good age to write a file and read it back. It finally catches a missing file with try and prints the caught result.
Note
never use try on a pure Either value, since there is no exception to catch.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
Which tool handles a missing file in IO?