2012-06-14 1 views
2

하스켈의 protocol-buffers에 문제가 있습니다. 간단한 UDP 수신자를 작성하고 오류가 발생합니다 :"ambiguous type 변수`msg0 '을 제약 조건에서 제거하는 방법"

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." } 

어떻게하면 되나요? (. 난 그냥 하스켈을 배우고)

내 코드는 다음과 같습니다

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 

답변

3

http://hackage.haskell.org/packages/archive/protocol-buffers/2.0.9/doc/html/Text-ProtocolBuffers-WireMessage.html#v:messageGet의 설명서에서 messageGet 타입 시그니처는 반환 값이 String 에러 메시지 또는 msg 및 잔류 ByteString 하나 인

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

이다. 그것은 (msg, ByteString) 반환하면 코드에서 해당 값이 변수 err에 바인딩,

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

를 작성했습니다. 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은 오류가없는 경우입니다 ("wrong"및 "right"라고 생각하십시오). 사례를 전환해도 자체적으로 오류 메시지가 제거되지는 않습니다.

+0

고마워요.하지만 X가 무엇인지 알아 내려고 노력하고 있습니다. 필자는 'Wire'(Wire에 대한 또 다른 주장이 필요함)와 'Wire Person'(유형으로 사용되는 Predicate Wire Person)을 시도했습니다. – fadedbee

+0

X = Person을 시도해 봤습니다. 답변을 주셔서 감사합니다. – fadedbee

1

이 같은 유형의 주석을 추가

return $ case messageGet (B.pack mesg) :: Either Something SomethingElse of 

(I 그래서, 프로토콜 버퍼에 익숙하지 않은 해요 어떤 유형이 SomethingSomethingElse인지 알 수 없으므로 필요한 실제 유형으로 교체하십시오.

관련 문제