二进制类型问题

发布于 2024-12-06 22:34:07 字数 1832 浏览 2 评论 0原文

我正在尝试使用 Haskell Bson 和我想保存和加载它们。保存似乎没有问题,但我在使用 Binary.get 函数时遇到输入错误。

这是我的代码:

{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances #-}
module Database.Axiom where

import Data.Bson (Document, Field)
import Data.Bson.Binary (putDocument, getDocument)
import Data.Binary as B (Binary(..), decodeFile, encodeFile)
import Control.Monad (liftM2)

instance Binary Document where
    put = putDocument
    get = getDocument

data Collection = Collection {
        collectionName :: ByteString,
        collectionDocs :: [Document]
    }

instance Binary Collection where
    put (Collection name docs) = B.put name >> B.put docs
    get = liftM2 Collection B.get B.get -- < Here is the type error

导致此错误:

Database/Axiom.hs:24:39:
    Overlapping instances for Binary [Field]
      arising from a use of `B.get'
    Matching instances:
      instance Binary a => Binary [a] -- Defined in Data.Binary
      instance Binary Document -- Defined at Database/Axiom.hs:13:10-24
    In the third argument of `liftM2', namely `B.get'
    In the expression: liftM2 Collection B.get B.get
    In an equation for `get': get = liftM2 Collection B.get B.get

问题是 Document 只是 [Field] 的同义词。但我需要一个 Binary Document 实例,因为没有函数可以序列化单个 Field。而且, BSON 确实不导出 Binary Field 的任何实例,因此我完全困惑为什么会首先发生此错误。

我尝试使用严格的类型声明,然后使用自制的 get 方法,但是 get :: [Document] 仅当存在 get 时才能很好地工作: :文档方法。

那么,也许有人可以帮助我?

I am trying to work with the Haskell Bson and I want to save and load them. The saving seems to be no problem, but I get a typing error with the Binary.get functions.

Here's my code:

{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances #-}
module Database.Axiom where

import Data.Bson (Document, Field)
import Data.Bson.Binary (putDocument, getDocument)
import Data.Binary as B (Binary(..), decodeFile, encodeFile)
import Control.Monad (liftM2)

instance Binary Document where
    put = putDocument
    get = getDocument

data Collection = Collection {
        collectionName :: ByteString,
        collectionDocs :: [Document]
    }

instance Binary Collection where
    put (Collection name docs) = B.put name >> B.put docs
    get = liftM2 Collection B.get B.get -- < Here is the type error

Which leads to this error:

Database/Axiom.hs:24:39:
    Overlapping instances for Binary [Field]
      arising from a use of `B.get'
    Matching instances:
      instance Binary a => Binary [a] -- Defined in Data.Binary
      instance Binary Document -- Defined at Database/Axiom.hs:13:10-24
    In the third argument of `liftM2', namely `B.get'
    In the expression: liftM2 Collection B.get B.get
    In an equation for `get': get = liftM2 Collection B.get B.get

The problem is that Document is merely a synonym of [Field]. But I need an instance for Binary Document, as there are no functions to serialize a single Field. And moreover, BSON does not export any instances for Binary Field, so I am completely confused why this error happens in the first place.

I tried it with strict type declaration and then to use a self made get method, but a get :: [Document] only works nicely when there's a get :: Document method.

So, anyone can help me, perhaps?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凡间太子 2024-12-13 22:34:07

虽然有点主观,但我认为最干净、最可靠的修复方法是为 Document 添加一个 newtype。像这样的东西:

import Control.Applicative ((<
gt;))
import Data.ByteString (ByteString)
import Data.Bson (Document, Field)
import Data.Bson.Binary (putDocument, getDocument)
import Data.Binary as B (Binary(..), decodeFile, encodeFile)
import Control.Monad (liftM2)

newtype CollectionDoc = CollectionDoc {unCollectionDoc :: Document}

instance Binary CollectionDoc where
    put = putDocument . unCollectionDoc
    get = CollectionDoc <
gt; getDocument

data Collection = Collection {
        collectionName :: ByteString,
        collectionDocs :: [CollectionDoc]
    }

instance Binary Collection where
    put (Collection name docs) = B.put name >> B.put docs
    get = liftM2 Collection B.get B.get

应该有效。此外,newtype 包装器已完全优化,因此运行时没有任何开销。

Altough a little subjective, I think the cleanest and most robust way to fix is is to add a newtype for Document. Something like:

import Control.Applicative ((<
gt;))
import Data.ByteString (ByteString)
import Data.Bson (Document, Field)
import Data.Bson.Binary (putDocument, getDocument)
import Data.Binary as B (Binary(..), decodeFile, encodeFile)
import Control.Monad (liftM2)

newtype CollectionDoc = CollectionDoc {unCollectionDoc :: Document}

instance Binary CollectionDoc where
    put = putDocument . unCollectionDoc
    get = CollectionDoc <
gt; getDocument

data Collection = Collection {
        collectionName :: ByteString,
        collectionDocs :: [CollectionDoc]
    }

instance Binary Collection where
    put (Collection name docs) = B.put name >> B.put docs
    get = liftM2 Collection B.get B.get

should work. In addition, newtype wrappers are completely optimized away, so there is no overhead at runtime.

短叹 2024-12-13 22:34:07

不要为 Document 定义实例;只需在 get 中调用 getDocument 而不是 B.get (我认为不需要使用 B. 进行限定) Collection 的 code> 定义。

Don't define the instance for Document; just call getDocument instead of B.get (which I see no need for qualifying with the B.) in your get definition for Collection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文