1
votes

Here's my problem

I'm using Control.Exception.catch for my exception handling, which has the following type: (culled from Hoogle)

catchSource
:: Exception e   
=> IO a 
The computation to run
-> (e -> IO a)  
Handler to invoke if an exception is raised
-> IO a  

Here is the constructor I will be passing to my handler function

> data JobException = PreProcessFail
>                   | JobFail
>                   | ChartFail
>                       deriving (Show, Typeable)

> instance Control.Exception JobException

Here is the Handler function as it is right now :

> exceptionHandler :: JobException -> IO ()
> exceptionHandler exception = do
>    writeFile "testException.txt" ("caught exception " ++ show exception )

I'm going to use this to do some logging. The information I need to log will be in a record of type JobState

> type JobState = MVar ProcessConfig

> data ProcessConfig = PConfig { model :: ServerModel
>                              , ipAddress :: String
>                              , cookie :: Cookie
>                              } deriving Show

So since I need a handler that is forced to have the type I mentioned above, and I need a JobState, I thought the answer would be to rewrite JobException to hide a JobState inside it. That seems to be a job for GADT! I'm not sure, this is new territory.

Am I right? Can I solve this with a GADT? Could someone provide a clue in how to begin to construct one? The tutorials I have been reading assume you're trying to solve a more complicated problem than what I have got.

If I am wrong, could someone point me in the right direction?

update: I learned about dynamic types from 1 and found shortly thereafter Data.Dynamic. Getting warmer?

Fun With Phantom Types

1
Why can't you just have a JobState in the exception? Why a GADT?augustss
The way I have the JobException set up now, is that functions throwing an exception will only be throwing a PreProcessFail or a JobFail, or a ChartFail. I need some way to include, for example a JobFail and a JobState. Having difficulty visualizing how to do that with standard types. Having read Fun With Phantom Types, it looks like that's the way I want to go. Could you give me a demonstration of what you mean?Michael Litchard
When I try to include a JobState in a JobException I get complaints about an instance of Show for JobState not existing. I have no idea how to write that instance seeing that a JobState is an MVar.Michael Litchard

1 Answers

3
votes

The Show instance of exceptions is mainly used when you don't handle an exception yourself and it gets printed out somewhere else in your program (e.g., at the top level). Since you're catching the exceptions with a custom handler, you should be able to just put JobState in the exception and give it a trivial Show instance .

For example:

data JobState = JobSuccess | JobFail deriving Show 
newtype JobException = JobException (MVar JobState) deriving Typeable
instance Show JobException where
    show _ = "JobException"
instance Exception JobException

exceptionHandler :: JobException -> IO ()
exceptionHandler (JobException m) = takeMVar m >>= print