首页 文章

Haskell protobuf:模糊类型变量

提问于
浏览
1

通常我知道如何修复模糊的类型变量问题,但这次不知道 . 长话短说,我使用protobuf Haskell库来处理protocol buffers . 该库让您忘记维护单独的.proto文件,如果它分别是Encode和Decode类型的实例,它会导致序列化和反序列化您的数据类型 .

我正在protobuf之上设计一个简单的协议 . 主消息数据类型包含消息ID,消息类型和一些取决于类型的可选数据 . 我想要一个获取消息ID,消息类型和可选数据(需要是Encode类的实例)的函数,并创建一个新的MyMessage实例,并将可选数据预先序列化为ByteString .

这就是我尝试这样做的方式:

{-# LANGUAGE DataKinds     #-}
{-# LANGUAGE DeriveGeneric #-}

import           Data.ByteString      (ByteString)
import           Data.Int
import           Data.Maybe
import           Data.Monoid
import           Data.ProtocolBuffers
import           Data.Serialize
import           Data.Text            (Text, pack)
import           GHC.Generics         (Generic)
import           GHC.TypeLits

data MyMsgType = MSG_TYPE_1
               | MSG_TYPE_2
               deriving (Enum, Show)

data MyMessage = MyMessage {
    msgId   :: Required 1 (Value Int64)
  , msgType :: Required 2 (Enumeration MyMsgType)
  , cpData  :: Optional 3 (Value ByteString)
} deriving (Generic, Show)

instance Encode MyMessage
instance Decode MyMessage

createMessage :: Encode a => Int64 -> MyMsgType -> Maybe a -> MyMessage
createMessage msgId msgType optionalData =
  MyMessage (putField msgId) (putField msgType) (putField $ serialiseOptionalData optionalData)

serialiseMessage :: MyMessage -> ByteString
serialiseMessage = runPut . encodeLengthPrefixedMessage

serialiseOptionalData :: Encode a => Maybe a -> Maybe ByteString
serialiseOptionalData Nothing    = Nothing
serialiseOptionalData (Just ctx) =
  Just . runPut . encodeLengthPrefixedMessage $ ctx

当我尝试使用createMessage函数时,我收到以下错误:

λ> createMessage 1 MSG_TYPE_1 Nothing

<interactive>:7:1:
    No instance for (Encode a0) arising from a use of ‘createMessage’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Encode MyMessage -- Defined at test.hs:24:10
      instance Encode
                 (unordered-containers-0.2.6.0:Data.HashMap.Base.HashMap
                    protobuf-0.2.1.0:Data.ProtocolBuffers.Wire.Tag
                    [protobuf-0.2.1.0:Data.ProtocolBuffers.Wire.WireField])
        -- Defined in ‘protobuf-0.2.1.0:Data.ProtocolBuffers.Encode’
    In the expression: createMessage 1 MSG_TYPE_1 Nothing
    In an equation for ‘it’: it = createMessage 1 MSG_TYPE_1 Nothing

有人可以解释为什么会出现这个错误以及如何解决它?我没有得到编译器看到歧义的确切位置 .

1 回答

  • 6

    您需要提供有关可选数据类型的更多信息 . 当您使用 Nothing 作为 Maybe a 类型的值时,编译器无法确定 a 的确切类型 . 你可以通过显式给 Nothing 类型来修复它,如 (Nothing :: Maybe Foo) .

相关问题