1

Data.Serialize に問題があります。データ構造をエンコードすると、Serialize クラスのインスタンスであるすべてのデータ構造をエンコードできます。それは非常にうまく機能します。

次に、ネットワーク経由で送信します。

ただし、デコードするときに問題があります。デコード関数は " Either String" と呼ばれる型を返しますが、これをさらに使用して元のデータ構造を再構築する方法がよくわかりません。受信者は、以前は のインスタンスであったことしか知りませんSerialize

receiveMessage :: Socket -> IO (a, SockAddr)
receiveMessage s  = do
        (msg, remoteSockAddr) <- recvFrom s 512
        return (S.decode $ msg, remoteSockAddr)

  Couldn't match type `a' with `Either String a0'
      `a' is a rigid type variable bound by
          the type signature for receiveMessage :: Socket -> IO (a, SockAddr)
    In the expression: decode $ msg
    In the first argument of `return', namely
      `(decode $ msg, remoteSockAddr)'
    In the expression: return (decode $ msg, remoteSockAddr)

eg を使用し receiveMessage :: (Serialize a) => Socket -> IO (a, SockAddr)ても役に立ちません。どうすればこれに対処し、元のデータ構造を取り戻すことができるでしょうか?

4

1 に答える 1

8

Eitherエラーを処理するためのタイプです。これは、任意の値(この場合はsome)を'sに対応する「エラー」の場合にMaybe関連付けることができることを除いて似ています。StringMaybeNothing

つまりEither String a、結果は、Stringまたは逆シリアル化するデータのいずれかになります。

Eitherパターンマッチングにより、データを取得できます。Either2つのコンストラクタがあります:LeftRight。この場合、Leftには文字列Rightがあり、値があります。したがって、次のようなことを行います。

case S.decode msg of
  Left str  -> ... -- handle your data not being deserialized correctly here
  Right res -> ... -- res is your data

また、結果がシリアル化可能なタイプであることを指定する必要があります。現在、関数は任意のreceiveMessageを返すことを約束しています。代わりに、クラスからのみ型を返すことができます。したがって、型署名をのようなものに変更します。aSerializeSerialize a => Socket -> IO (a, SockAddr)

実際に関数を使用すると、Haskellどのタイプaが想定されているかがわかり、適切な逆シリアル化コードが選択されます。ただし、このコードは型クラスのインスタンスにのみ存在するためSerialize、型シグネチャで指定する必要があります。

$無関係な注意:。の演算子は必要ありませんS.decode $ msg。演算子は、それに続くものを囲む親を追加するものと考えることができるため、このS.decode $ msg行は、と同等ですS.decode (msg)。これは不要であり、そのままにしておくことができますS.decode msg

于 2012-06-28T22:27:15.293 に答える