我有一个只用过两个不同参数的GADT,ForwardPossible和():
-- | 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)
我想派生足够的Data.Data实例来涵盖OrForward t()和OrForward t ForwardPossible。我不认为一般(数据t,数据转发)=> OrForward t forward实例是可能的,除非它普遍忽略OFForward,但是数据的重叠实例t => OrForward t ForwardPossible和(Data t,Data forward)=>如果有办法让ghc派生那些实例,那么OrForward t forward实例可能是一个解决方案。
我尝试过定义:
deriving instance Data t => Data (OrForward t ())
deriving instance Data t => Data (OrForward t ForwardPossible)
然后ghc给我一个这样的错误:
Duplicate type signature:
Structure.hs:53:1-70: $tOrForward :: DataType
Structure.hs:52:1-49: $tOrForward :: DataType
答案 0 :(得分:2)
我找到了解决这个问题的一种相当不干净的方法,所以我会把它放在这里以防其他人没有找到更好的答案:
我在主要结构模块的顶部创建了两个新模块,专门用于派生实例。我使用一个来获取GADT专业化的实例,使用ForwardPossible,一个用于实例take(),使用StandaloneDeriving和FlexibleInstances。这避免了ghc添加的代码中的内部符号冲突问题,通过将它们放在不同的模块中来实现Data.Data。
我必须写实例数据t =>数据(OrForward t())手动排除OFForward案例:
instance Data t => Data (OrForward t ()) where
gfoldl k z (OFKnown a1) = (z OFKnown `k` a1)
gunfold k z c = 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
数据t =>的实例数据(OrForward t ForwardPossible)可以派生出来:
deriving instance Data t => Data (OrForward t ForwardPossible)