rnso
rnso

Reputation: 24565

Why this try catch example is not working

I have following demo code from here:

import System.Environment  
import System.IO  
import System.IO.Error  

main = toTry `catch` handler  

toTry :: IO ()  
toTry = do (fileName:_) <- getArgs  
           contents <- readFile fileName  
           putStrLn $ "The file has " ++ show (length (lines contents)) ++ " lines!"  

handler :: IOError -> IO ()  
handler e = putStrLn "Whoops, had some trouble!"

But it is giving me error:

runghc trycatch2.hs 

trycatch2.hs:5:14: error:
    Variable not in scope: catch :: IO () -> (IOError -> IO ()) -> t

Where is the problem and how can it be solved? Thanks.

Upvotes: 3

Views: 174

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476813

The example in Learn You a Haskell for the Greater Good is outdated, the catch :: Exception e => IO a -> (e -> IO a) -> IO a function is part of Control.Exception.

System.IO.Error however still has a catch function that is here applicable: catchIOError :: IO a -> (IOError -> IO a) -> IO a, but as the documentation says:

The catchIOError function establishes a handler that receives any IOException raised in the action protected by catchIOError. An IOException is caught by the most recent handler established by one of the exception handling functions. These handlers are not selective: all IOExceptions are caught.

(...)

Non-I/O exceptions are not caught by this variant; to catch all exceptions, use catch from Control.Exception.

So you can fix the problem here by using catchIOError (since you are dealing with an IOError, but as specified in the documentation, this only covers a limited set of exceptions), or you can import catch from Control.Exception:

import Control.Exception(catch)

import System.Environment  
import System.IO  
import System.IO.Error

main :: IO ()
main = toTry `catch` handler  

toTry :: IO ()  
toTry = do (fileName:_) <- getArgs  
           contents <- readFile fileName  
           putStrLn $ "The file has " ++ show (length (lines contents)) ++ " lines!"

handler :: IOError -> IO ()  
handler e = putStrLn "Whoops, had some trouble!"

Upvotes: 2

Related Questions