Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the 'right way' to use Haskell types with MongoDB nested data?

I have two simple data types in Haskell:

data Ticket = Ticket {
  tbody :: String,
  tauthor :: String,
  tcomments :: [TicketComment]
}
data TicketComment = TicketComment {
  tcbody :: String,
  tcauthor :: String
}

Ignoring for a moment the lack of timestamps, and the use of strings vs. bytestrings, I simply want to store the comments in MongoDB nested in their tickets.

Up until now I have been using a rather simple instance to store data:

class MongoIO a where
  transout :: a -> [Field]
  transin :: [Field] -> (Maybe a)

The implementation then looks something like this:

instance MongoIO Ticket where
  transout a = [("body" =: tbody a),
               ("author" =: tauthor a),
               ("comments" =: tcomments a)]
  transin a = case (,,) <$> look "body" a
                         <*> look "author" a
                         <*> look "comments" a of
                 Nothing -> Nothing
                 Just (bo,au,co) ->
                   Just $ Ticket (typed bo) (typed au) (typed co)

As would be expected, this breaks down at ("comments" =: tcomments a). I'm confident that I'm getting into an area of Haskell types where my own knowledge is lacking so I'm excited to hear about how others would approach this.

like image 621
clintm Avatar asked Dec 10 '10 15:12

clintm


2 Answers

You have to translate embedded documents also. So

instance MongoIO Ticket where
  transout t = [
    "body" =: tbody t,
    "author" =: tauthor t,
    "comments" =: map transout (tcomments t) ]
  transin d = Ticket
    <$> lookup "body" d
    <*> lookup "author" d
    <*> (mapM transin =<< lookup "comments" d)

plus similar instance for TicketComment.

Also I would use the type synonym Document for [Field].

like image 109
Tony Hannan Avatar answered Nov 04 '22 15:11

Tony Hannan


It looks like you just have the transin and transout implementations reversed in your instance. Your transin takes a Ticket and returns a list of Fields; but that's transout's type.

like image 23
Jason Orendorff Avatar answered Nov 04 '22 13:11

Jason Orendorff