In The acquire-use-release cycle section from Real World Haskell, the type of bracket is shown:
ghci> :type bracket bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
Now, from the description of bracket, I understand that an exception might be thrown while the function of type a -> IO c is running. With reference to the book, this exception is caught by the calling function, via handle:
getFileSize path = handle (\_ -> return Nothing) $ bracket (openFile path ReadMode) hClose $ \h -> do size <- hFileSize h return (Just size)
I can't help but thinking that when the exception does occur from within bracket's 3rd argument, bracket is not returning an IO c.
How does this go well with purity?
I think the answer might be exactly this, but I'm not sure.