我可以派生一个Data的新类型实例吗?

时间:2018-09-25 10:55:22

标签: haskell ghc

我有一个新类型T

newtype T = T Text

我想为此导出Data。所以有了-XGeneralizedNewtypeDeriving -XDerivingStrategies,我做到了

deriving newtype instance Data T

我希望这是对GHC的轻松理解,但是我收到了令人讨厌的错误消息(如下所示)。错误消息似乎来自coerce派生而导致的newtype应用。

如果我正确理解角色注释,它们将需要在Data的实例方法上进行类型声明,但是没有。我需要滚动自己的实例吗?

    • Couldn't match representation of type ‘c1 Text’
                               with that of ‘c1 T’
        arising from a use of ‘ghc-prim-0.5.2.0:GHC.Prim.coerce’
      NB: We cannot know what roles the parameters to ‘c1’ have;
        we must assume that the role is nominal
    • In the expression:
        ghc-prim-0.5.2.0:GHC.Prim.coerce
          @(forall (c :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep
                         -> TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
            forall (d :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep)
                   (b :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
            Data d => c (d -> b) -> d -> c b
            -> forall (g :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
               g -> c g
               -> Text -> c Text)
          @(forall (c :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep
                         -> TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
            forall (d :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep)
                   (b :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
            Data d => c (d -> b) -> d -> c b
            -> forall (g :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
               g -> c g
               -> T -> c T)
          gfoldl
      In an equation for ‘gfoldl’:
          gfoldl
            = ghc-prim-0.5.2.0:GHC.Prim.coerce
                @(forall (c :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep
                               -> TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
                  forall (d :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep)
                         (b :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
                  Data d => c (d -> b) -> d -> c b
                  -> forall (g :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
                     g -> c g
                     -> Text -> c Text)
                @(forall (c :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep
                               -> TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
                  forall (d :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep)
                         (b :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
                  Data d => c (d -> b) -> d -> c b
                  -> forall (g :: TYPE ghc-prim-0.5.2.0:GHC.Types.LiftedRep).
                     g -> c g
                     -> T -> c T)
                gfoldl
      When typechecking the code for ‘gfoldl’
        in a derived instance for ‘Data T’:
        To see the code I am typechecking, use -ddump-deriv
      In the instance declaration for ‘Data T’

可能与之相关:GeneralizedNewtypeDeriving fails for PersistFieldSql

编辑:也许我应该只使用-XDeriveDataTypeable

1 个答案:

答案 0 :(得分:4)

来自docs

  

派生实例仅适用于这些形式的声明   (扩展任何类型的同义词后):

newtype T v1..vn                   = MkT (t vk+1..vn) deriving (C t1..tj)
newtype instance T s1..sk vk+1..vn = MkT (t vk+1..vn) deriving (C t1..tj)
     

其中[...]

     
      
  • C不是ReadShowTypeableData。这些类不应“浏览”类型或其构造函数。您仍然可以得出这些   新类型的类,但是它以通常的方式发生,而不是通过这种方式发生   新机制。同意Default deriving strategy
  •   

要点是:Data的{​​{1}}实例应根据newtype本身的构造函数而不是基础类型的(几个)构造函数进行构造。

广义的newtype实例只是将基础类型的newtype实例“强制”到Data,但这是错误的。

(不过,您收到的错误消息可能会更有帮助。)

结论:尝试改为使用newtype。那应该得到正确的实例。

DeriveDataTypeable

更准确地说,我们应该在适当的情况下查看此信息:

newtype T = T Text deriving (Data)

相反,在这里,“派生出新类型”的实例将产生> data U = A | B deriving Data > newtype T = T U deriving Data > toConstr (T A) T ,从而公开了基础构造函数而不是预期的A