How can I get a Data instance for GADT in Haskell?

I have a GADT that is used with only two different parameters: ForwardPossible and ():

-- | Used when a forward definition is possible. data ForwardPossible = ForwardPossible deriving (Eq, Ord, Typeable, Data, Show) -- | GADT which accepts forward definitions if parameter is ForwardPossible. data OrForward t forward where OFKnown :: t -> OrForward t forward OFForward :: NamespaceID -> SrcSpan -> BS.ByteString -> OrForward t ForwardPossible deriving instance Eq t => Eq (OrForward t forward) deriving instance Ord t => Ord (OrForward t forward) deriving instance Typeable2 OrForward deriving instance Show t => Show (OrForward t forward) 

I would like to get enough Data.Data instances to cover both OrForward t () and OrForward t ForwardPossible. I do not think that a common (Data t, Data forward) => Orforward t forward instance is possible if it does not ignore OFFORward at all, but either overlaps the instances for Data t => OrForward t ForwardPossible and (Data t, Data forward) = > Direct OrForward instances may be the solution if there is a way to make ghc to get those instances.

I tried to determine:

 deriving instance Data t => Data (OrForward t ()) deriving instance Data t => Data (OrForward t ForwardPossible) 

but then ghc gives me this error:

 Duplicate type signature: Structure.hs:53:1-70: $tOrForward :: DataType Structure.hs:52:1-49: $tOrForward :: DataType 
+4
source share
1 answer

I found a rather unclean way around the problem, so I will post it here if no one else finds a better answer:

  • I created two new modules on top of the main structural module specifically for receiving instances. I used it to get GADT specialization instances using ForwardPossible, and for an instance () instance using StandaloneDeriving and FlexibleInstances. This avoided the problem of conflicting internal characters from the code added by ghc to implement Data.Data by putting them in different modules.

  • I had to write an instance of Data t => Data (OrForward t ()) manually to rule out the case of OFFORward:

     instance Data t => Data (OrForward t ()) where gfoldl kz (OFKnown a1) = (z OFKnown `k` a1) gunfold kzc = case constrIndex c of _ -> k (z OFKnown) toConstr _ = cOFKnown dataTypeOf _ = tOrForward dataCast2 f = gcast2 f tOrForward :: Data.Data.DataType tOrForward = mkDataType "Data.FieldML.Structure.OrForward" [cOFKnown] cOFKnown :: Data.Data.Constr cOFKnown = mkConstr tOrForward "OFKnown" [] Prefix 
  • An instance can be obtained for the data t => Data (OrForward t ForwardPossible):

     deriving instance Data t => Data (OrForward t ForwardPossible) 
+2
source

Source: https://habr.com/ru/post/1436022/


All Articles