什么是正确使用Data.Serialize“Either String”

时间:2012-06-28 22:21:22

标签: haskell

我有Data.Serialize的问题。当我编码数据结构时,我可以编码作为Serialize类实例的所有数据结构。这很有效。

然后我通过网络发送它。

然而,解码时遇到问题。解码函数给了我一个名为“Either String”的类型,我不太确定如何进一步使用它来重建我的原始数据结构,因为收件人只知道它以前是{{1的实例}}

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) 也没有帮助。我怎么能处理这个并最好地恢复我的原始数据结构?

1 个答案:

答案 0 :(得分:8)

Either是一种处理错误的类型。它与Maybe类似,但您可以将任意值(在本例中为某些String)与对应于Maybe的{​​{1}}的“错误”案例相关联。

也就是说,Nothing表示结果可能是Either String a或要反序列化的数据。

您可以通过模式匹配从String中获取数据。 Either有两个构造函数:EitherLeft。在这种情况下,Right会有一些字符串,Left会有你的价值。所以你会做这样的事情:

Right

此外,您必须指定结果是某些可序列化类型。现在,您的case S.decode msg of Left str -> ... -- handle your data not being deserialized correctly here Right res -> ... -- res is your data 函数承诺返回任何类型receiveMessage;相反,您只能从a类返回一个类型。因此,请将类型签名更改为Serialize

当您实际使用函数时,Serialize a => Socket -> IO (a, SockAddr)将知道Haskell应该是什么类型,并将选择适当的反序列化代码。但是,由于此代码仅存在于a类型类的实例中,因此必须在类型签名中指定。

在不相关的说明中:您不需要Serialize中的$运算符。您可以将运算符视为围绕其后面的内容添加parens,因此S.decode $ msg行等同于S.decode $ msg,这是不必要的,可以保留为S.decode (msg)