Below is a module that attempts to implement a Serialize instance for a simple GADT. Unfortunately the get implementation for the Reorder constructor complains that there is no Ixed a constraint. Is there any way, beautiful or ugly, to implement this? I can't add Ixed a to the instance context because the Update constructor needs to work for values that don't satisfy this constraint.
{-# LANGUAGE GADTs #-} import Control.Lens (Index, Ixed) import Data.Serialize -- | Two different ways of updating a value - replacing it completely or, -- if it is an instance of Ixed, re-ordering it. data Op a where Update :: Serialize a => a -> Op a Reorder :: (Ixed a, Serialize (Index a)) => [Index a] -> Op a instance Serialize a => Serialize (Op a) where put (Update a) = putWord8 1 >> put a put (Reorder ks) = putWord8 2 >> put ks get = do i <- getWord8 case i of 1 -> Update <$> get 2 -> Reorder <$> get _ -> error "instance Serialize (Op a) - corrupt data" Addendum: One simplification to this might be to make the type variable a a phantom type, so that Op looks like this:
data Op a where Update :: Serialize a => ByteString -> Op a Reorder :: (Ixed a, Serialize (Index a)) => [ByteString] -> Op a The type could then be used to properly decode the byte strings. Not sure whether this helps
https://stackoverflow.com/questions/65941212/how-to-write-a-serialize-instance-for-this-gadt January 29, 2021 at 12:25AM
没有评论:
发表评论