2016-04-18 35 views
1

通常我知道如何解决模糊类型变量问题,但现在不知道。长话短说,我使用protobuf Haskell库来处理protocol buffers。这个库让你忘记了维护单独的.proto文件,如果它分别是一个Encode和Decode类型的实例,它会派生出序列化和反序列化数据类型的方式。Haskell protobuf:含糊类型变量

我正在protobuf之上设计一个简单的协议。有一个主消息数据类型包含一个消息ID,消息类型和一些依赖于类型的可选数据。我想要一个获取消息ID,消息类型和可选数据(必须是Encode类的实例)的函数,并提前创建一个带有可选数据序列化为ByteString的MyMessage的新实例。

这就是我尝试这样做:

{-# 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 

有人能解释我为什么这个错误发生以及如何修复它?我不明白编译器看到的含糊不清之处。

回答

6

您需要提供有关可选数据类型的更多信息。当您使用Nothing作为Maybe a类型的值时,编译器无法推断确切的a是什么类型。您可以通过明确指定类型为Nothing来修复它,如(Nothing :: Maybe Foo)

+0

欢呼的伴侣,你无法想象我花了多少时间试图弄清楚什么是错的:) –