Reputation: 24565
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
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 anyIOException
raised in the action protected bycatchIOError
. An IOException is caught by the most recent handler established by one of the exception handling functions. These handlers are not selective: allIOExceptions
are caught.(...)
Non-I/O exceptions are not caught by this variant; to catch all exceptions, use
catch
fromControl.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