代码之家  ›  专栏  ›  技术社区  ›  Lukas Süsslin

如何在Haskell中将数据类型转换为BSON?

  •  1
  • Lukas Süsslin  · 技术社区  · 8 年前

    我一直在试图理解如何使用Haskell的 Data.Bson.Mapping 然而,我无法理解它,在 docs 也没什么帮助。

    我应该如何解决此问题?似乎还没有发布任何关于这方面的问题。我将在下面附上相关代码,以便您能够理解我的来历。

    {-# LANGUAGE TemplateHaskell #-}
    
    module Main where
    import Database.MongoDB.Connection  (host, connect)
    import Database.MongoDB.Query       (access, master, insertMany)
    import Data.Data                    (Typeable)
    import Data.Bson.Mapping
    
    data Item a = Item { content :: a
                       , checked :: Bool
                       } deriving (Eq, Show, Typeable)
    

    到目前为止我所做的

    • 选择字段,但我不知道如何将表达式(Q Exp)更改为文档
    • 实现deriveBson,但我得到了与文档中示例相同的错误

    请注意,我对Haskell还是相当陌生的,我花了2个小时寻找解决方案,但就是想不出来。

    非常感谢。

    1 回复  |  直到 8 年前
        1
  •  3
  •   epsilonhalbe    8 年前

    您提到了一个错误,但没有发布错误本身,因此我对此无能为力,但序列化您的数据类型应该相当简单

    data Item a = Item { content :: a
                       , checked :: Bool
                       } deriving (Eq, Show, Typeable)
    
    instance (Bson a) => Bson (Item a) where
      toBson (Item cont check) = ["content" := Doc (toBson cont)
                                 ,"checked" := Bool check]
      fromBson d = do cont  <- "content" `lookup` d
                      check <- "checked" `lookup` d
                      pure $ Item cont check
    

    toBson 必须创建 Document 这只是类型的同义词 [Field] 其中字段仅为 Label 与标记值关联。当然我们必须要求 a 实现序列化和反序列化,以便 Item 的实例 Bson 。

    对于反序列化,我选择了 lookup 函数,该函数返回一元值,即如果找到该值,则返回该值;如果没有找到,则返回失败的方法。E、 g.如果我们的单子是 Maybe 然后它会返回一个 Nothing 如果未找到,则 Just x 否则,对于IO,我们将得到一个运行时错误(这是我们想要避免的)。所以打电话的时候 toBson ... 确保你以理智的方式执行它 Maybe _ 或 Either String _ 。

    使用测试

    toBson ["no-content":=Int64 1, "checked":= Bool True] :: Maybe (Item Int)
    toBson ["content":=Int64 1, "unchecked":= Bool True] :: Either String (Item Int)
    

    如果您想手动跳过一个实现,您需要向我显示错误,我很乐意帮助您解决出现的问题。