2012-12-07 26 views
0
记录

说我有一个记录,其中一个值是一个MVAR:JSON编码包括MVAR

data SomeRecord = SomeRecord { frobs :: MVar Integer } 

,我希望能够编码/使用埃宋它从JSON解码。编码时,MVar将被解开并且原始值被编码,并且相反将在解码时发生。

这将是很好能够只写一个返回IO (Maybe SomeRecord)和返回IO ByteString一个的toJSON实例FromJSON实例,但因为解析器单子不是MonadIO的一个实例,我不认为这是可能的。

到目前为止,我已经采取了编写函数来翻译MVar设防的记录和几乎相同的没有MVar类型的记录之间的转换,然后对其进行编码/解码。

我试图找到一些方法来保持MVar超出我的记录。看起来这将是理想的。但是,假设我无论如何不能这样做,是否有更简单的方法来处理JSON编码/解码?

编辑:

我不知道如果我问错了问题。也许我的整个方法是不正确的。我想要做的是允许一群连接的客户端(每个都在不同的线程上)添加/编辑/删除对象列表。这里是什么类型的样子:

-- 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 
    ... 
    } 

每个“房间”有一个Instance持有该房的对象。 Instance本身位于MVar中,用于同步对iObjects散列映射的添加/删除操作,并且每个单独的存储位于MVar中,以便在更新单个对象时不必阻止整个数据结构。

所以更新操作过程如下所示:

  • 上的实例readMVar获得在iObjects哈希
  • M.lookup特定的商店
  • modifyMVar在店里做了更新

有没有像使用嵌套MVars更习惯性的haskell方法?理想情况下,可以使MVar远离数据,从而保持整个结构的简单性。

回答

5

没有,你有原始埋葬在一个纯数据结构的并发。这总是会有点尴尬处理。你正在走私副作用到任何试图触摸你的MVar。

尝试通过参数化是对整数容器中的数据类型。例如。

data T a = T { frobs :: c Integer } 

那么你就可以工作,它实例化T MVar,以及流媒体,拆开包装,然后在其上为T One,其中data One a = One a操作。

+0

我明白了,'''''''''类型的巧妙手段。我想这正是我正在寻找的! – jhickner

0

FromJSON和ToJSON类型的类只有在编写解析/打印代码时才提供便利。如果我们没有他们,我们仍然可以编写解析器和打印机,他们只需要更多的样板。正如你发现的那样,这些类型的类没有用不纯的值来处理。所以基本上,你一直坚持使用另一种方法和附带的附加样板。

有几个选项可以让它更好。您可以复制FromJSON和ToJSON并将其修改为支持使用monadic IO的解析器和打印机。如果你使用这种模式很多,这可能是值得的。或者,你可以使用unsafePerformIO,虽然这看起来像一个真的坏主意......也许甚至不值得一提,因为如果你不确切知道你在做什么,它可能很容易引起大问题。

和当然,就像你提到的,你可以尝试让你的结构纯净。这对我来说似乎是最好的方法。你可以有另一个具有MVars的结构,然后是一个从不纯的结构中填充纯结构的函数。通过这种方式,纯粹的结构可以作为更易于JSON解析/打印可变结构的路径。