Say I have a record where one value is an MVar:
data SomeRecord = SomeRecord { frobs :: MVar Integer }
and I want to be able to encode/decode it from JSON using Aeson. When encoding, the MVar would be unwrapped and the raw value encoded, and the reverse would happen on decoding.
It would be nice to be able to just write a FromJSON instance that returns an IO (Maybe SomeRecord)
and a ToJSON instance that returns an IO ByteString
, but since the Parser monad isn't an instance of MonadIO I don't think that's possible.
So far I've resorted to writing functions to translate between the MVar-encumbered record and a nearly identical record without the MVar type, and then encoding/decoding that.
I've tried to find some way to keep the MVar out of my record in the first place. It seems like that would be ideal. But supposing that I can't do that for whatever reason, is there an easier way to handle the JSON encoding/decoding?
EDIT:
I wonder if I'm asking the wrong question. Maybe my whole approach is incorrect. What I'm trying to do is allow a bunch of connected clients (each on a different thread) to add/edit/delete a list of objects. Here's what the types look like:
-- the data type for each "room"
data Instance = Instance
{ iName :: T.Text
, iObjects :: M.HashMap T.Text (MVar Store)
...
}
-- the data type for a particular object in the room that can be changed
data Store = Store
{ sObject :: A.Value
...
}
Each "room" has an Instance
that holds that rooms objects. The Instance itself is in an MVar to synchronize additions/deletions of the iObjects
hashmap, and each individual store is in an MVar so that the whole data structure doesn't have to block while an individual object is updated.
So an update operation proceeds like this:
- readMVar on the instance to get at the iObjects hash
- M.lookup a particular store
- modifyMVar on the store to do the update
Is there a more idiomatic haskell approach than using nested MVars like this? Ideally some way that kept the MVars away from the data so persisting the whole structure would be simple.