Reputation: 3230
I'd like to catch exceptions from the IO and inspect what kind of exception was raised with typeOf
and then use the specific exception to pattern match in order to handle the exception specifically. But the following code doesn't work as I expected.
import Control.Exception (SomeException, handle)
import Data.Typeable (typeOf)
import System.Environment (getEnv)
main :: IO ()
main = handle missingEnv exe
where
exe = do
env <- getEnv "MISSING_ENV"
print env
file <- readFile "/file-does-not-exist"
print file
missingEnv :: SomeException -> IO ()
missingEnv e = do
print e
print $ typeOf e
return ()
The above code will print the following error, but it only shows "SomeException", which doesn't have the specific name for the type of the Exception.
MISSING_ENV: getEnv: does not exist (no environment variable)
SomeException
You might suggest me to use lookupEnv
, but that's not my point, because I'd like to learn how to catch an exception, rather than how to avoid an exception.
Is it possible to inspect the specific "type" of a raised exception from IO
?
Also is it possible to inspect the specific "type" of a raised exception from MonadError
?
Upvotes: 1
Views: 393
Reputation: 152837
You've subverted the entire exception-type-matching mechanism by using SomeException
. If you want to handle a specific kind of exception, just do that, don't convert into and out of SomeException
along the way. For example:
import Control.Exception (IOException, handle, throwIO)
import System.Environment (getEnv)
import System.IO.Error (isDoesNotExistError)
main :: IO ()
main = handle missingEnv exe
where
exe = do
env <- getEnv "MISSING_ENV"
print env
file <- readFile "/file-does-not-exist"
print file
missingEnv :: IOException -> IO ()
missingEnv e | isDoesNotExistError = print e
| otherwise = throwIO e
Upvotes: 2
Reputation: 3071
Yes, you can inspect the type of the exception:
logSomeException :: SomeException -> IO ()
logSomeException (SomeException e) = print (typeOf e)
Upvotes: 2