如何派生 Data.Messagepack 1.0.0 的实例

How to derive instances of Data.Messagepack 1.0.0

上一版本Data.Messagepack,0.7.2.5 supports deriving instances via Template Haskell. The current version (1.0.0), however, doesn't.

因此我想知道是否有另一种方法可以自动派生 MessagePack 1.0.0 实例,可能使用 XDeriveGeneric?

作为权宜之计,请查看 message-pack github 存储库的 msgpack-aeson 目录:

https://github.com/msgpack/msgpack-haskell/tree/master/msgpack-aeson

您可以从您的数据值 <-> aeson <-> 消息包。不一定高效,但方便,因为您可以使用 DeriveGeneric.

自动派生 ToJSON 和 FromJSON

示例代码:

{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}

import Data.MessagePack.Aeson
import qualified Data.MessagePack as MP
import GHC.Generics
import Data.Aeson

data Foo = Foo { _a :: Int, _b :: String }
  deriving (Generic)

instance ToJSON Foo
instance FromJSON Foo

toMsgPack :: Foo  -> Maybe MP.Object
toMsgPack =   decode . encode

test = toMsgPack (Foo 3 "asd")

您可以编写自己的 GMessagePack class 并通过派生 Generic 来获取实例。我试着这样做来回答这个问题,但我不推荐它。 msgpack 不支持求和,并且 one sum type supported by the Haskell msgpack library, Maybe 的编码非常差。

instance MessagePack a => MessagePack (Maybe a) where
  toObject = \case
    Just a  -> toObject a
    Nothing -> ObjectNil

  fromObject = \case
    ObjectNil -> Just Nothing
    obj -> fromObject obj

Maybe的编码无法区分Nothing :: Maybe (Maybe a)Just Nothing :: Maybe (Maybe a),两者都会被编码为ObjectNil,解码为Nothing.如果我们要将显而易见的定律 fromObject . toObject == pure 强加给 MessagePack 个实例,MessagePack 的这个实例就会违反它。