I have the following that works similar to
forkIO, but returns a blocking "channel" that lets you receive the result of a forked IO computation. My main concern is its handling of exceptions. It will return
Nothing if something is raised, but can't supply any more information then that.
I tried using
try inside of
wrapAction, which returns an
(Either Exception a), but I couldn't figure out what exception type to use. I tried
SomeException thinking it would catch everything, and supply a message, but it doesn't. Running a computation that divides by 0 resulted in
Right being returned, but threw a "divide by 0" exception when I tried inspecting the result. Surely in a generic situation like this I can't specifically catch every possible exception (given a user could create their own). How should I set up the exception handling so that a
Leftcan be returned with an exception message?
import Control.Concurrent import Control.Exception data RThread a = RThread (IO a) (MVar (Maybe a)) newReturn :: IO a -> IO (RThread a) newReturn act = newEmptyMVar >>= return . RThread act wrapAction :: RThread a -> IO () wrapAction (RThread act chan) = onException (act >>= putMVar chan . Just) (putMVar chan Nothing) returnFork :: IO a -> IO (RThread a) returnFork act = do nR <- newReturn act forkIO $ wrapAction nR return nR waitForResult :: RThread a -> IO (Maybe a) waitForResult (RThread _ chan) = takeMVar chan
Any critique would be appreciated
import System.Random import Control.Monad testFn :: IO [Int] testFn = returnFork (replicateM 100 $ randomRIO (1,100) >>= waitForResult
Although realistically you would pass the result of
waitForResult somewhere else to wait.