将Haskell类型与MongoDB嵌套数据一起使用的“正确方法”是什么?

时间:2010-12-10 15:34:34

标签: haskell mongodb

我在Haskell中有两种简单的数据类型:

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

暂时忽略时间戳的缺失,以及字符串与字节串的使用,我只想将注释存储在嵌套在门票中的MongoDB中。

到目前为止,我一直在使用一个相当简单的实例来存储数据:

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

然后实现如下所示:

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)

如预期的那样,这会在("comments" =: tcomments a)处发生。我有信心进入Haskell类型的领域,我自己的知识缺乏,所以我很高兴听到别人会如何处理这个问题。

2 个答案:

答案 0 :(得分:8)

您还必须翻译嵌入式文档。所以

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)

加上TicketComment的类似实例。

另外,我会为Document使用类型同义词[Field]

答案 1 :(得分:2)

您的实例看起来只是颠倒了transintransout实现。您的transin需要Ticket并返回Field个列表;但那是transout的类型。