[Haskell-beginners] how to catch the error thrown by openFile?
Daniel Fischer
daniel.is.fischer at googlemail.com
Sat Sep 24 21:21:59 CEST 2011
On Saturday 24 September 2011, 19:52:24, Ovidiu Deac wrote:
> Given this function
>
> f :: MyMonad String
> f = do
> liftIO $ putStrLn "Please enter a file name: "
> name ← liftIO getLine
> hFile ← liftIO $ openFile name ReadMode
> content ← liftIO $ hGetContents hFile
> return $ content
>
> I would like to catch the error thrown by openFile and translate it to
> my own exception type.
>
> So first I tried this:
> hFile ← (liftIO $ openFile name ReadMode) `catch` λ_ → throwError
> (KnownErr "open failed")
catch has type (IO a -> (e -> IO a) -> IO a) [where e = IOError if you're
using Prelude.catch, and e can be any instance of Exception if you're using
Control.Exception.catch (recommended)].
But (liftIO ioAction) has type (MyMonad a), so that can't be used as an
argument to catch.
Nor can (\_ -> throwError (KnownErr "...")).
>
> ..but it fails because the error handler is returning a different type
> then the "try block". Right?
No, it fails because both have the wrong type for catch.
It would typecheck with catchError instead of catch, but that wouldn't
catch the error :(
>
> Then I tried this:
> f = do
> liftIO $ putStrLn "Please enter a file name: "
> name ← liftIO getLine
> hFile ← (liftIO $ openFile name ReadMode ↠ return.Right)
> `catch` λ_ → return (Left $ KnownErr "open failed")
Close. If you replace liftIO with ErrorT in that line and move the first
open parenthesis past the $, then it works and does what you want. Without
changing the following two lines (or, better, do change them;
do x <- act
return x
is the same as just
act
). liftIO adds a layer of Either, ErrorT doesn't.
hFile <- ErrorT $ liftM Right (openFile name ReadMode)
`catch` (\_ -> return $ Left (KnownErr "open failed"))
liftIO $ hGetContents hFile
More information about the Beginners
mailing list