开发者

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 开发者_StackOverflow社区into an area of Haskell types where my own knowledge is lacking so I'm excited to hear about how others would approach this.


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜