Exceptions in Yesod
exception, haskell, json, yesod
Solution
Philosophically speaking, in the Haskell/Yesod world you want to pass the values forward, rather than return them backwards. So instead of having the handlers return a value, have them call forwards to the next step in the process, which may be to generate an exception.
Remember that you can bundle any amount of future actions into a single object, so you can pass a continuation object to your handlers and foos that basically tells them, "After you are done, run this blob of code." That way they can be void and return nothing.
Problem
I had made a daemon that used a very primitive form of `ipc` (telnet and send a String that had certain words in a certain order). I snapped out of it and am now using `JSON` to pass messages to a `Yesod` server. However, there were some things I really liked about my design, and I'm not sure what my choices are now. Here's what I was doing: ``` buildManager :: Phase -> IO () buildManager phase = do let buildSeq = findSeq phase jid = JobID $ pack "8" config = MkConfig $ Just jid flip C.catch exceptionHandler $ runReaderT (sequence_ $ buildSeq <*> stages) config -- ^^ I would really like to keep the above line of code, or something like it. return () ``` each function in buildSeq looked like this ``` foo :: Stage -> ReaderT Config IO () data Config = MkConfig (Either JobID Product) BaseDir JobMap ``` `JobMap` is a `TMVar Map` that tracks information about current jobs. so now, what I have are Handlers, that all look like this ``` foo :: Handler RepJson ``` `foo` represents a command for my daemon, each handler may have to process a different JSON object. What I would like to do is send one `JSON` object that represents success, and another JSON object that espresses information about some exception. I would like `foo`s helper function to be able to return an `Either`, but I'm not sure how I get that, plus the ability to terminate evaluation of my list of actions, `buildSeq`. Here's the only choice I see 1) make sure `exceptionHandler` is in Handler. Put `JobMap` in the `App` record. Using `getYesod` alter the appropriate value in `JobMap` indicating details about the exception, which can then be accessed by `foo` Is there a better way? What are my other choices? Edit: For clarity, I will explain the role of`Handler RepJson`. The server needs some way to accept commands such as `build` `stop` `report`. The client needs some way of knowing the results of these commands. I have chosen JSON as the medium with which the server and client communicate with each other. I'm using the Handler type just to manage the JSON in/out and nothing more.