KnowledgeHub
Questions
Tags
Users
Search
Alex Rivera
|
Logout
Edit Question
Title
Body
The question is similar to this question. However, this one is about exceptions, not about lazy I/O. Here is a test: {-# LANGUAGE ScopedTypeVariables #-} import Prelude hiding ( catch ) import Control.Exception fooLazy :: Int -> IO Int fooLazy m = return $ 1 `div` m fooStrict :: Int -> IO Int fooStrict m = return $! 1 `div` m test :: (Int -> IO Int) -> IO () test f = print =<< f 0 `catch` \(_ :: SomeException) -> return 42 testLazy :: Int -> IO Int testLazy m = (return $ 1 `div` m) `catch` \(_ :: SomeException) -> return 42 testStrict :: Int -> IO Int testStrict m = (return $! 1 `div` m) `catch` \(_ :: SomeException) -> return 42 So I wrote two functions fooLazy which is lazy and fooStrict which is strict, also there is two tests testLazy and testStrict , then I try to catch division by zero: > test fooLazy *** Exception: divide by zero > test fooStrict 42 > testLazy 0 *** Exception: divide by zero > testStrict 0 42 and it fails in lazy cases. The first thing that comes to mind is to write a version of the catch function that force the evaluation on its first argument: {-# LANGUAGE ScopedTypeVariables #-} import Prelude hiding ( catch ) import Control.DeepSeq import Control.Exception import System.IO.Unsafe fooLazy :: Int -> IO Int fooLazy m = return $ 1 `div` m fooStrict :: Int -> IO Int fooStrict m = return $! 1 `div` m instance NFData a => NFData (IO a) where rnf = rnf . unsafePerformIO catchStrict :: (Exception e, NFData a) => IO a -> (e -> IO a) -> IO a catchStrict = catch . force test :: (Int -> IO Int) -> IO () test f = print =<< f 0 `catchStrict` \(_ :: SomeException) -> return 42 testLazy :: In
Tags (comma-separated)
Save Edits
Cancel