6

ForwardPossible と () の 2 つの異なるパラメーターでのみ使用される 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)

OrForward t () と OrForward t ForwardPossible の両方をカバーするのに十分な Data.Data インスタンスを派生させたいと考えています。一般的な (Data t, Data forward) => OrForward t forward インスタンスは可能だとは思わないOrForward t forward インスタンスは、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
4

1 に答える 1

3

この問題を回避するためのかなり不潔な方法を見つけたので、他の誰もより良い答えを見つけられない場合に備えて、ここに記載します。

  1. 特にインスタンスを派生させるために、メインの Structure モジュールの上に 2 つの新しいモジュールを作成しました。1 つは ForwardPossible を取る GADT 特殊化のインスタンスを派生させるために使用し、もう 1 つは () を取るインスタンスに使用し、StandaloneDeriving と FlexibleInstances を使用しました。これにより、ghc によって追加されたコードからの競合する内部シンボルの問題が回避され、Data.Data を異なるモジュールに配置することで実装されました。

  2. OFForward ケースを除外するには、インスタンス Data t => Data (OrForward t ()) を手動で記述する必要がありました。

    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. Data t => Data (OrForward t ForwardPossible) のインスタンスは次のように導出できます。

    deriving instance Data t => Data (OrForward t ForwardPossible)
    
于 2012-09-24T23:53:44.797 に答える