2012-09-24 25 views
4

我有仅曾经与两个不同的参数,ForwardPossible和()中使用的GADT:如何在Haskell中为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吨()和OrForward吨ForwardPossible。我认为一般(Data t,Data forward)=> OrForward t向前实例是可能的,除非它普遍忽略向前,但是对于Data 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 
+3

作为一个小纸条,如果你使用GHC 7.4或7.6与'DataKinds',你可以有'数据OrForward吨(向前::布尔)',然后你的两种类型是'OrForward t True'和'OrForward t False“(或者当然你可以制作你自己的2型并使用它来代替'Bool')。 – Cactus

回答

2

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

  1. 我创建了主结构M顶部的两个新模块模块专门用于派生实例。我使用了一个派生实例GADT专业化服务ForwardPossible,一个实例采取(),使用StandaloneDeriving和FlexibleInstances。这避免了由ghc添加的代码将内部符号与其他模块中的Data.Data实现相互冲突的问题。

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

    deriving instance Data t => Data (OrForward t ForwardPossible) 
    
相关问题