I have a problem with protocol-buffers in Haskell. I’m writing a simple UDP receiver and get the error:
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." }
How can I follow it’s advice? (I’m just learning Haskell.)
My Code follows:
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
From the documentation at http://hackage.haskell.org/packages/archive/protocol-buffers/2.0.9/doc/html/Text-ProtocolBuffers-WireMessage.html#v:messageGet, the type signature of
messageGetisThe return value is either a
Stringerror message or amsgand a residualByteString. In your code, you have writtenIf it returns a
(msg, ByteString), that value is bound to the variableerr. Sinceerris ignored, the actual type ofmsgis not determined, which is what the error message is telling you. In fact, any type that’s an instance ofWireandReflectDescriptorwill work, but the program will behave differently for each type! Since the compiler doesn’t know what type you want, you have to specify it. You can specify it by annotating the return type ofmessageGet.You probably also meant to switch the
LeftandRightcases in your code.Rightis the non-error case (think “wrong” and “right”). Switching the cases will not get rid of the error message on its own.