我有一个 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。我不认为一般的 (Data t, Dataforward) => OrForward t 转发实例是可能的,除非它普遍忽略 OFForward,但是 Data t => OrForward t ForwardPossible 和 (Data t, Dataforward) => 的重叠实例如果有办法让 ghc 派生这些实例,OrForward t 转发实例可能是一个解决方案。
我尝试过定义:
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
我发现了一种相当不干净的方法来解决这个问题,所以我将其放在这里,以防其他人找到更好的答案:
我在主结构模块之上创建了两个新模块,专门用于派生实例。我使用了一种方法来派生采用 ForwardPossible 的 GADT 专业化实例,另一种方法用于采用 () 的实例,利用 StandaloneDeriving 和FlexibleInstances。这避免了 ghc 添加的代码中通过将它们放在不同的模块中来实现 Data.Data 的内部符号冲突的问题。
-
我必须手动编写实例 Data t => Data (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
-
Data t => Data(或转发到转发可能)的实例可以导出:
deriving instance Data t => Data (OrForward t ForwardPossible)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)