Haskell中GeneralizedNewtypeDeriving编译拓展用法相关疑问
问题1:第一段代码中GeneralizedNewtypeDeriving(GND)的使用问题
- 现有代码中GND的使用部分正确:通过GND派生
Identity a的Num、Eq、Show实例的逻辑是生效的,只要内部类型a有对应类的实例,Identity a就可以自动获得透传的实例,这也是Identity 1可以正常构造的原因。 - 无需手动编写带
(Num a, NewConstraint a)约束的NewConstraint (Identity a)实例的思路完全可行,问题出在没有将NewConstraint加入deriving的类列表中。GND的核心作用就是自动为newtype生成指定类的透传实例,未指定要派生NewConstraint的情况下,自然需要手动编写对应实例。 - 要实现自动派生
NewConstraint的效果,仅需修改newtype定义如下:
newtype Identity a = Identity a deriving (Eq, Show, Num, NewConstraint)
此时GND会自动生成约束为NewConstraint a => NewConstraint (Identity a)的实例,无需手动实现getTrue方法,也不需要额外添加Num a的冗余约束。
问题2:GeneralizedNewtypeDeriving的适用场景
调整后的代码无需开启GND即可运行,是因为没有用到GND的特性:代码中手动实现了NewConstraint (Identity a)的实例,仅派生的Show属于Haskell标准支持的默认可派生类,不需要拓展支持。
GND的核心适用场景如下:
- 为已有类型封装newtype做语义隔离时,复用内部类型的类实例,避免手写大量透传的模板代码。例如定义
newtype UserId = UserId Int时,可通过GND派生Eq、Ord、Num等实例,无需手动实现每个方法的透传逻辑。 - 突破标准deriving的限制:Haskell默认仅允许派生
Eq、Ord、Show、Read、Enum、Bounded这几个固定类的实例,GND支持派生任意符合条件的类的实例,包括自定义类型类。 - 保证实例逻辑和内部类型完全一致,避免手动实现出现逻辑错误。
内容的提问来源于stack exchange,提问作者maxloo
相关产品推荐
相关产品推荐

