haskell - 如何摆脱 "Ambiguous type variable ` 消息 0' in the constraints"

标签 haskell protocol-buffers

我在 Haskell 中遇到 Protocol Buffer 问题。我正在编写一个简单的 UDP 接收器并收到错误:

src/Main.hs:39:25:
    Ambiguous type variable `msg0' in the constraints:
      (Wire msg0)
        arising from a use of `messageGet' at src/Main.hs:39:25-34
      (Text.ProtocolBuffers.Reflections.ReflectDescriptor msg0)
        arising from a use of `messageGet' at src/Main.hs:39:25-34
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: (messageGet (B.pack mesg))
    In the second argument of `($)', namely
      `case (messageGet (B.pack mesg)) of {
         Left person -> putStrLn $ show person
         Right err -> error $ "Failed to parse address book." }'
    In a stmt of a 'do' block:
      return
      $ case (messageGet (B.pack mesg)) of {
          Left person -> putStrLn $ show person
          Right err -> error $ "Failed to parse address book." }

我如何遵循它的建议? (我刚刚学习 Haskell。)

我的代码如下:

module Main where

import Data.Bits
import Network.Socket -- hiding (send, sendTo, recv, recvFrom)
-- import Network.Socket.ByteString
import Network.BSD
import Data.List
import qualified Data.ByteString.Lazy.Char8 as B
import Text.ProtocolBuffers.Header (defaultValue, uFromString)
import Text.ProtocolBuffers.WireMessage (messageGet, messagePut, Wire)

import Data.Sequence ((><), fromList)

import AddressBookProtos.AddressBook
import AddressBookProtos.Person
import AddressBookProtos.Person.PhoneNumber
import AddressBookProtos.Person.PhoneType

import Network.Socket
import System.Posix.Directory
import System.Posix.Files
import System.Posix.IO
import System.Posix.Process
import System.Exit


echoserver :: IO ()
echoserver = do
           withSocketsDo $ do
                   sock <- socket AF_INET Datagram 0
                   bindSocket sock (SockAddrInet 4567 iNADDR_ANY)
                   socketRx sock

socketRx :: Socket -> IO ()
socketRx sock = do

         (mesg, recv_count, client) <- recvFrom sock 1500

         return $ case (messageGet (B.pack mesg)) of
                       Left person -> putStrLn $ show person
                       Right err   -> error $ "Failed to parse address book."
         socketRx sock



main::IO()
main = echoserver

最佳答案

来自 http://hackage.haskell.org/packages/archive/protocol-buffers/2.0.9/doc/html/Text-ProtocolBuffers-WireMessage.html#v:messageGet 的文档,messageGet 的类型签名为

messageGet :: (ReflectDescriptor msg, Wire msg) => ByteString -> Either String (msg, ByteString)

返回值是String错误消息或msg和剩余的ByteString。在您的代码中,您已经编写了

case messageGet (B.pack mesg) of
  Left person -> putStrLn $ show person
  Right err   -> error "Failed to parse address book."

如果它返回一个(msg, ByteString),则该值将绑定(bind)到变量err。由于 err 被忽略,因此无法确定 msg 的实际类型,这就是错误消息告诉您的内容。事实上,作为 WireReflectDescriptor 实例的任何类型都可以工作,但程序对于每种类型的行为会有所不同!由于编译器不知道您想要什么类型,因此您必须指定它。您可以通过注释 messageGet 的返回类型来指定它。

case messageGet (B.pack mesg) :: Either String (X, ByteString) of -- Use the actual message type in place of 'X'
  Left person -> putStrLn $ show person
  Right err   -> error "Failed to parse address book."

您可能还想在代码中切换 LeftRight 大小写。 Right 是非错误情况(认为“错误”和“正确”)。切换大小写不会自行消除错误消息。

关于haskell - 如何摆脱 "Ambiguous type variable ` 消息 0' in the constraints",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11033236/

相关文章:

haskell - 使用 State Monad 插入树

opengl - GLU NURBS 渲染错误

haskell - `sequenceA` 的工作原理

c++ - 如何将包含嵌入空值的 Google Protocol Buffer SerializeAsString() 输出分配给 std::string?

protocol-buffers - 如何从 protobuf (.proto) 文件在 (.json/.yaml) 中生成 swagger3 (OpenAPI3) 规范?

rest - spring mvc Rest Protocol Buffer http 406 Not Acceptable 错误

java - 如何在 Android 上使用 google/api/annotations.proto

haskell - 如何在 haskell 中将函数提升到转换后的 monad?

haskell - 我可以在 Haskell 中声明一个 NULL 值吗?

python - protobuf3,python - 如何将元素设置为 map<string,OtherMessage> 字典?