-->

我怎样才能得到一个数据实例在Haskell一个GADT?(How can I derive a Da

2019-07-31 21:04发布

我有一个只能用两个不同的参数,ForwardPossible和()使用的GADT:

-- | 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牛逼ForwardPossible。 我不认为一般的(数据T,数据转发)=> OrForward吨向前实例是可能的,除非它普遍忽略OFForward,但无论是对重叠实例数据T => OrForward吨ForwardPossible和(数据T,数据转发)=> OrForward T个前向实例可能是一个解决方案,如果有一种方法,使GHC获得这些实例。

我曾尝试定义:

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

Answer 1:

我发现了一个相当不洁净的方法来解决这个问题,所以我把它放在这里的情况下,没有人找到一个更好的答案:

  1. 我创建了主体结构模块的顶部的两个新模块专门为获得实例。 我用一个派生实例GADT专业化服用ForwardPossible,以及一个用于实例采取(),利用StandaloneDeriving和FlexibleInstances的。 这避免了由GHC添加通过把它们放在不同的模块来实现Data.Data代码冲突的内部符号的问题。

  2. 我不得不写实例数据T =>数据(OrForward吨())手动排除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 
  3. 为数据T实例=>数据(OrForward吨ForwardPossible)可以导出:

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


文章来源: How can I derive a Data instance for a GADT in Haskell?