radrow
radrow

Reputation: 7139

Why can't I catch exception in different IO than () in Haskell?

I want to catch all exceptions in IO String function. When I run this code:

import Control.Exception.Base

handler :: SomeException -> IO String
handler _ = return "Gotta catch'em all!"

boom :: IO String
boom = return (show (3 `div` 0))

get :: IO String
get = boom `catch` handler

main :: IO()
main = do
  x <- get
  print x

I get

exctest: divide by zero

However this code works:

import Control.Exception.Base

handler2 :: SomeException -> IO ()
handler2 _ = print "Gotta catch'em all!"

boom2 :: IO ()
boom2 = print $ show (3 `div` 0)

main :: IO()
main = do
  boom2 `catch` handler2

with result

> Gotta catch'em all!

When I change boom in first example to

boom = error "ERR"

The exception is caught ok. Why does it behave this way? What should I do to catch exception in first example?

Upvotes: 2

Views: 188

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

This has nothing to do with () vs. other types. Note that the following also doesn't catch:

boom = return $ error "ERR"

The reason catch won't do anything about that is that return is lazy, thus the error isn't actually triggered by catch, only if you try to get at the contained value.

It is for precisely this reason that the Exception module has evaluate, which is equivalent to return but strict.

boom :: IO String
boom = evaluate . show $ 3`div`0

Upvotes: 8

Related Questions