I trying to develop heavy network application and i use ProtoBuf for description network messages.
This is simplified version of my code. It doesn't work because of monomorphism restriction.
class Message a where
pack :: a -> ByteString
unpack :: ByteString -> Maybe a
data HelloMsg = HelloMsg deriving Show
instance Message HelloMsg -- ... using protobuf
data PingMsg = PingMsg deriving Show
instance Message PingMsg -- ... using protobuf
data PongMsg = PongMsg deriving Show
instance Message PongMsg -- ... using protobuf
-- and more 50 another...
data MsgType = Hello | Ping | Pong -- | and more 50 another ...
data CommonMsg a = CommonMsg MsgType a deriving Show
instance (Message a) => CommonMsg a where
pack (CommonMsg type msg) = concat [packType type, pack msg]
unpack bin = let (type, rest) = unpackType bin in CommonMsg type <$> unpack rest
-- here i need unpack message depend on type
receiver :: Chan (CommonMsg a) -> IO ()
receiver out = void $ forkIO $ forever $ do
msg <- unpack <$> getCommonMsgFromNet
writeChan out
main = do
input <- newChan
receiver input
forver $ do
msg <- readChan input
putStrLn $ show msg
What workarounds exist? Link to the project with a similar architecture is highly desirable
UPDATE: Rephrase my question - i need polymorphic approach deserialize ByteString to Message depend on message type.