[Haskell-cafe] Using catch and errors

Cale Gibbard cgibbard at gmail.com
Fri Apr 22 11:16:18 EDT 2005


On 4/22/05, Alexandre Weffort Thenorio <alethenorio at home.se> wrote:
> I am trying to get catch to work but I guess I am total newbie on this one.
> 
> main :: IO()
> main =  do
>   removeFile "./newint.hex"
>   hexFile <- catch (readFile int.hex)  (\_ -> do putStrLn "Cannot find
> int.hex"
>         getLine --Simply stop program so user can read error message
>         return() --Quit)
>  hexFile <- readFile "int.hex"
> --res of program goes here
> getLine
> return()

Well, there are a number of problems here. 

The one with getLine is actually probably a layout issue -- you should
indent the getLine so that it lines up with the putStrLn.

Also, return () is simply an IO action that does nothing, returning
the zero tuple, it's basically a no-op and will not cause anything to
quit. If you want your program to exit, you should import System, and
use exitWith ExitSuccess or exitWith (ExitFailure n), where n is the
Int failure code you want to pass back to the shell. You can also just
let the last IO action in the definition of main execute and return
whatever value it likes, which will be ignored, and your program will
terminate normally:
main = putStrLn "Hello, World!"
is a complete Haskell program. :) Note also that you only need to
write "do" if you'll be joining multiple actions together.

In this case, return () is a type error, as the type of catch is IO a
-> (IOError -> IO a) -> IO a, and readFile is of type IO String, so
the function that you pass as a second parameter has to return an IO
String (the action to be performed in case of an error, whose result
will be substituted for that of the readFile).

(There's also the obvious syntax error of not quoting the string
"int.hex", but I suspect you would have caught that one.)

After the catch, you have another instance of the readFile command you
would have just run, which you probably don't want.

What you're probably looking for is something like this:

import Directory
import System

main :: IO()
main =  do hexFile <- catch (readFile "int.hex")
                            (\_ -> do putStrLn "Cannot find int.hex"
                                      getLine
                                      exitWith ExitSuccess)
           print hexFile

It's important that getLine is aligned with putStrLn and the rest of
the do block, if you use something like the emacs haskell-mode, you
can have your editor align this automatically, or semi-automatically
for you.

> 
> But it keeps giving me error on getLine. How can I quit a program in case of
> an error giving an error message?
> 
> Also I tried something like
> 
> main :: IO()
> main =  do
>             ex <- doesFileExist "./newint.hex"
>              if ex then removeFile "./newint.hex"
> 
> But that won't work either. Any ideas? I'd like to catch different errors
> and quit program giving different error messages

This bit is mostly correct, except that your 'if' is missing its
'then'. You could write:

import Directory

main :: IO()
main =  do ex <- doesFileExist "./newint.hex"
           if ex
               then removeFile "./newint.hex"
               else return ()
-- (recall that return () is a no-op)

but it's probably better style to use "when", which is defined in the
Monad library:

import Directory
import Monad

main :: IO()
main =  do ex <- doesFileExist "./newint.hex"
           when ex (removeFile "./newint.hex")

> 
> Last but not least I have the function
> 
> outputLine keyno key orgFile = do
>     let part1 = getLeft keyno (orgFile!!1)
>     let part2 = getRight keyno (orgFile!!1)
>     let total = part1 ++ (map toUpper key) ++ part2
>     let checks = checksum (drop 1 total)
>     let final = total ++ checks ++ "\n"
>     newHexFile <- openFile "newint.hex" WriteMode
>      hPutStrLn newHexFile (orgFile!!0 ++ "\n" ++ final ++ unlines (drop 2
> orgFile))
> 
> I'd like to be able to check for stuff such as size of key and wheter keyno
> is only 1 or 0 and quit program with error message otherwise but again
> couldn't quite get catch to work.
> 
Why not try checking them directly with 'if' or 'case' and performing
the corresponding action accordingly?

> Any reading tips about subject would be appreciated.
> 
Check out the wiki:
http://www.haskell.org/hawiki/HaskellNewbie
-- lots of beginner questions and answers have been accumulated there.

Also, to really understand what's going on with the do-notation, it
would be best that you learn what monads are about. I'll direct you at
the "All About Monads" tutorial:
http://www.nomaware.com/monads/html/
And of course, my own take on them:  :)
http://www.haskell.org/hawiki/MonadsAsContainers

Hope this helps,
 - Cale

> Best Regards
> 
> NooK
> 


> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>


More information about the Haskell-Cafe mailing list