2

Haskell のプロトコル バッファに問題があります。私は単純な 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
4

2 に答える 2

3

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)、その値は変数にバインドされますerr。は無視されるためerr、 の実際の型はmsg決定されません。これは、エラー メッセージが示す内容です。実際、andのインスタンスであるすべての型が機能しますが、プログラムは型ごとに異なる動作をします! コンパイラは必要な型を認識していないため、指定する必要があります。の戻り値の型に注釈を付けることで指定できます。WireReflectDescriptormessageGet

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

おそらく、コード内で Leftandのケースを切り替えることも意図していたでしょう。エラーのないケースです (「間違っている」と「正しい」と考えてください)。ケースを切り替えても、それ自体ではエラー メッセージが取り除かれません。RightRight

于 2012-06-14T13:38:45.503 に答える
1

次のような型注釈を追加します。

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

(私はプロトコルバッファに精通していないので、どのタイプが必要なのかわかりませんSomethingSomethingElse必要な実際のタイプに置き換えてください。)

于 2012-06-14T13:32:36.630 に答える