我有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)
也没有帮助。我怎么能处理这个并最好地恢复我的原始数据结构?
答案 0 :(得分:8)
Either
是一种处理错误的类型。它与Maybe
类似,但您可以将任意值(在本例中为某些String
)与对应于Maybe
的{{1}}的“错误”案例相关联。
也就是说,Nothing
表示结果可能是Either String a
或要反序列化的数据。
您可以通过模式匹配从String
中获取数据。 Either
有两个构造函数:Either
和Left
。在这种情况下,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)
。