KMC
KMC

Reputation: 1742

How to catch exception

How do you handle error in Haskell? Let's say I have function that does division. It returns true if division can be performed otherwise return false.

di :: Int -> Bool
di a b = a `div` b

How do I catch the exception in this type of scenario so that I can return boolean value? How do I catch all exception not just particular type of exception? I know I can check if b is zero or not but I just want to know error handling.

Update : Here's what I have done so far. However I'm getting type mismatch error. Can anyone point out how I can fix this?

di :: Int -> Int -> Bool
di a b = do
    result <- try (a `div` b) :: IO (Either SomeException Bool)
    case result of
       Left ex  -> False
       Right val -> True

Error

Couldn't match type ‘IO b0’ with ‘Bool’
Expected type: IO (Either SomeException Bool)
               -> (Either SomeException Bool -> IO b0) -> Bool
  Actual type: IO (Either SomeException Bool)
               -> (Either SomeException Bool -> IO b0) -> IO b0

Upvotes: 3

Views: 1606

Answers (1)

ErikR
ErikR

Reputation: 52039

Couple of problems with your code:

  • di runs in the IO monad, so the result type needs to be IO Bool
  • try needs an IO computation, but div a b is a pure value, so you need to lift it with return.
  • Again, di returns an IO Bool, so the last case statement needs a return to lift the case expression to an IO computation.

Here's a version of di which type checks:

di' :: Int -> Int -> IO Bool
di' a b = do
  r <- try (return (div a b)) :: IO (Either SomeException Int)
  return $ case r of
             Left _ -> False
             Right _ -> True

However, this version will return True for all inputs. The reason is that due to lazy evaluation the div function is never actually called.

One way to fix this is to use the BangPatterns pragma to force the evaluation:

{-# LANGUAGE BangPatterns #-}

di' :: Int -> Int -> IO Bool
di' a b = do
  r <- try (let !x = div a b in return x) :: IO (Either SomeException Int)
  return $ case r of
            Left _ -> False
            Right _ -> True

ghci> di' 3 0
False

ghci> di' 3 1
True

Also see this SO question: How to catch a divide by zero error in Haskell? for details on how to catch only arithmetic exceptions.

Upvotes: 2

Related Questions