我有一个新类型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
?
答案 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不是
Read
,Show
,Typeable
或Data
。这些类不应“浏览”类型或其构造函数。您仍然可以得出这些 新类型的类,但是它以通常的方式发生,而不是通过这种方式发生 新机制。同意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
。