我有這樣的事情:
data MsgDir = InMD | OutMD
data Msg
= ResourcesM
| TagsM
deriving (Enum, Eq, Show)
data MsgPkt (msg::Msg) (msgDir::MsgDir) where
GetResourcesMP :: MsgPkt 'ResourcesM 'OutMD
MyResourcesMP :: Int -> Int -> String -> MsgPkt 'ResourcesM 'InMD
GetTagsMP :: MsgPkt 'TagsM 'OutMD
MyTagsMP :: [String] -> MsgPkt 'TagsM 'InMD
class MsgId (msg::Msg) (msgDir::MsgDir) where msgId :: Word8
instance MsgId 'ResourcesM 'OutMD where msgId = fromIntegral $ fromEnum ResourcesM
instance MsgId 'TagsM 'OutMD where msgId = fromIntegral $ fromEnum TagsM
'TagsM我為(for 'OutMD, )寫了幾個實體'InMD:
instance forall m d. (m ~ 'TagsM, d ~ 'OutMD) => MessagePack (MsgPkt 'TagsM 'OutMD) where
toObject GetTagsMP = toObject (msgId @m @d)
fromObject o = do
msg::Word8 <- fromObject o
when (msg /= msgId @m @d) (fail $ "Unexpected MESSAGE: " <> show msg)
pure GetTagsMP
instance forall m d. (m ~ 'TagsM, d ~ 'InMD) => MessagePack (MsgPkt 'TagsM 'InMD) where
toObject (MyTagsMP a) = toObject (msgId @m @d, a)
fromObject o = do
(msg::Word8, a) <- fromObject o
when (msg /= msgId @m @d) (fail $ "Unexpected MESSAGE: " <> show msg)
pure $ MyTagsMP a
在為'ResourcesM我寫相同的幾個實體之前 - 是否有可能減少手工作業 - 也許有一些通用的?其實我有不止TagsM, ResourcesM,所以手動編碼會很繁瑣。這些建構式(如GetResourcesMP, MyResourcesMP)可以有不同數量的引數(以及不同型別的引數)。我什至不確定是否可以使用泛型(或類似的東西)來簡化它。
如何撰寫這樣一個通用實體,所以使用簡單的“自動”/“半自動”是派生MessagePack的所有這些實體?
uj5u.com熱心網友回復:
一種方法是為唯一部分創建一個類,并根據它實作共享部分。這種方法的缺點是它需要您控制訊息包物件格式;如果您需要與其他一些工具兼容,這種方式將行不通。
class Packable a where
type Packed a
pack :: a -> Packed a
unpack :: Packed a -> a
instance Packable (MsgPkt 'TagsM 'OutMD) where
type Packed (MsgPkt 'TagsM 'OutMD) = ()
pack _ = ()
unpack _ = GetTagsMP
instance Packable (MsgPkt 'TagsM 'InMD) where
type Packed (MsgPkt 'TagsM 'InMD) = [String]
pack (MyTagsMP ss) = ss
unpack = MyTagsMP
instance (Packable (MsgPkt m d), MessagePack (Packed (MsgPkt m d)))
=> MessagePack (MsgPkt m d) where
toObject mp = toObject (msgId @m @d, pack mp)
fromObject o = do
(msg, packed) <- fromObject o
when (msg /= msgId @m @d) (fail $ "Unexpected MESSAGE: " <> show msg)
pure (unpack packed)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/452949.html
標籤:哈斯克尔
