1

I've been trying to understand how to transform a Data type into a Document with Haskell's Data.Bson.Mapping package, however, I couldn't figure it out and the example in the docs didn't help much either.

How should I resolve this problem? No questions regarding this seem to have been posted yet. I'll attach relevant code below, so you may be able to understand where I'm coming from.

{-# 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)

What I've tried so far

  • selectFields, but I don't know how to change the Expression (Q Exp) into a Document
  • Implementing deriveBson, but I got the same error as with the example from the Docs

Please note, I'm still fairly new to Haskell and I have spent 2 hours looking for a solution, but just couldn't figure it out.

Thank you.

Lukas Süsslin
  • 553
  • 1
  • 3
  • 12

1 Answers1

4

You speak of an error but don't post the error itself so I cannot help with that - but serializing your data type should be fairly straightforward

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 has to create a Document which is just a type synonym for [Field] where Field is just a Label associated with a tagged value. Of course we have to require a to implement serialization and de-serialization in order to make Item an instance of Bson.

For the de-serialization I chose the lookup function which gives back a monadic value i.e. the value if found and a way to fail if not. E.g. if our monad is Maybe then it would give back a Nothing if not found and a Just x otherwise, for IO we would get a run-time error (something we want to avoid). so when calling toBson ... make sure you execute it in a sane monad like Maybe _ or Either String _.

Test it with

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

If you want to skip an implementation by hand - you need to show me the error, I'd be happy to help you with what went wrong.

epsilonhalbe
  • 15,637
  • 5
  • 46
  • 74