Как преобразовать тип данных в BSON в Haskell?

Я пытался понять, как преобразовать тип данных в документ с помощью 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)

Что я уже пробовал

  • selectFields, но я не знаю, как изменить выражение (Q Exp) в документ
  • Реализую производныйBson, но получил ту же ошибку, что и в примере из Docs

Обратите внимание, я все еще довольно новичок в Haskell, и я потратил 2 часа на поиск решения, но просто не мог его понять.

Спасибо.


person Luke Mueller    schedule 13.03.2018    source источник
comment
Работает ли производныйBson, если ваш Item не является параметрическим в «a»? Кроме того, какую ошибку вы получаете?   -  person Marc Talbot    schedule 13.03.2018
comment
Макросы bson-mapping Template Haskell выглядят немного странно — по какой причине вы предпочитаете этот пакет bson-generic или одному из конвертеров в Aeson?   -  person leftaroundabout    schedule 13.03.2018
comment
@leftaroundabout Я только что попытался использовать собственный пакет Data.Bson!   -  person Luke Mueller    schedule 14.03.2018
comment
@MarcTalbot Я пробовал, но это не помогло. Получение TemplateHaskell не работает   -  person Luke Mueller    schedule 14.03.2018


Ответы (1)


Вы говорите об ошибке, но не публикуете саму ошибку, поэтому я не могу с этим помочь, но сериализация вашего типа данных должна быть довольно простой.

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], где Field - это просто Label, связанный с помеченным значением. Конечно, мы должны потребовать от a реализовать сериализацию и десериализацию, чтобы сделать Item экземпляром Bson.

Для десериализации я выбрал функцию lookup, которая возвращает монадическое значение, то есть значение, если оно найдено, и способ отказа, если нет. Например. если наша монада равна Maybe, то она вернет Nothing, если не найдена, и Just x в противном случае, для ввода-вывода мы получим ошибку времени выполнения (чего мы хотим избежать). поэтому при вызове 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)

Если вы хотите пропустить реализацию вручную - вам нужно показать мне ошибку, я буду рад помочь вам с тем, что пошло не так.

person epsilonhalbe    schedule 13.03.2018
comment
ps: код не скомпилирован - не берите с собой ghc прямо сейчас - person epsilonhalbe; 13.03.2018
comment
большое спасибо, это очень удивительное объяснение и решение! Вы много думали об этом. Я ценю старания ☺️ - person Luke Mueller; 14.03.2018