【问题标题】:JSON encoding a record that includes an MVarJSON 编码包含 MVar 的记录
【发布时间】:2012-11-25 23:48:07
【问题描述】:

假设我有一个记录,其中一个值为 MVar:

data SomeRecord = SomeRecord { frobs :: MVar Integer }

我希望能够使用 Aeson 从 JSON 编码/解码它。编码时,MVar 会被解包并编码原始值,而解码时会发生相反的情况。

如果能够编写一个返回 IO (Maybe SomeRecord) 的 FromJSON 实例和一个返回 IO ByteString 的 ToJSON 实例,那就太好了,但由于 Parser monad 不是 MonadIO 的实例,我不认为这是可能的。

到目前为止,我已经求助于编写函数来在 MVar-encumbered 记录和几乎相同的没有 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 hashmap 的添加/删除,每个单独的存储都位于一个 MVar 中,这样整个数据结构就不必在单个对象更新时阻塞。

所以更新操作是这样进行的:

  • 在实例上读取 MVar 以获取 iObjects 哈希
  • M.查找特定商店
  • 在商店中修改MVar 以进行更新

有没有比使用这样的嵌套 MVar 更惯用的 Haskell 方法?理想情况下,某种使 MVar 远离数据的方法很简单。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    不,您有一个并发原语隐藏在纯数据结构中。处理起来总是有点尴尬。您正在将副作用走私到任何试图触及您的 MVar 的东西中。

    尝试通过 Integer 的容器参数化数据类型。例如

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

    然后您可以将其实例化为T MVar,然后进行流式处理,解包,然后将其作为T One 操作,其中data One a = One a

    【讨论】:

    • 我明白了,One 类型的巧妙技巧。我想这正是我想要的!
    【解决方案2】:

    FromJSON 和 ToJSON 类型类实际上只是为了在编写解析/打印代码时提供方便。如果我们没有它们,我们仍然可以编写解析器和打印机,它们只是需要更多样板。正如您所发现的,这些类型类的制定方式并不适用于不纯的值。所以基本上,你会被另一种方法和随之而来的额外样板卡住。

    有几个选项可以让它变得更好。您可以复制 FromJSON 和 ToJSON 并修改它们以支持使用 monadic IO 的解析器和打印机。如果你经常使用这种模式,那可能是值得的。或者,您可以使用 unsafePerformIO,尽管这似乎是一个真的 坏主意...也许甚至不值得一提,因为如果您不确切知道自己在做什么,它很容易导致大问题。

    当然,就像您提到的那样,您可以尝试使您的结构纯净。这对我来说似乎是最好的方法。您可以拥有另一个具有 MVar 的结构,然后是一个从不纯结构填充纯结构的函数。这样一来,纯结构就可以作为更轻松地解析/打印可变结构的 JSON 的路径。

    【讨论】:

      猜你喜欢
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-15
      • 2020-10-05
      • 1970-01-01
      相关资源
      最近更新 更多