2016-04-18 8 views
1

通常、私はあいまいな型の変数の問題を修正する方法を知っていますが、今回はありません。長い話を簡単に言えば、protocol buffersで働くために、私はprotobufハスケルライブラリを使用しています。ライブラリでは、別々の.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

オプションのデータの種類について詳しく知る必要があります。タイプMaybe aの値としてNothingを使用すると、コンパイラは正確にaの型を推測できません。 (Nothing :: Maybe Foo)のように、タイプをNothingに明示的に指定して修正できます。

+0

私は何が間違っているか把握するのに費やした時間を想像することはできません:) –

関連する問題