20

来自 GHC 的手册,Section Safe Language

模块边界控制——使用安全语言编译的 Haskell 代码保证只能访问通过其他模块导出列表公开可用的符号。其中一个重要部分是,安全编译的代码无法使用无法导入的数据构造函数检查或创建数据值。如果模块 M 通过仔细使用其导出列表建立了一些不变量,则使用导入 M 的安全语言编译的代码保证尊重这些不变量。因此,Haskell 模板和GeneralizedNewtypeDeriving在安全语言中被禁用,因为它们可用于违反此属性。

如何使用 打破模块的不变量GeneralizedNewtypeDeriving

4

1 回答 1

29

Luqui 链接到我关于该主题的博客文章。基本上,GeneralizedNewtypeDeriving正如在 GHC 中实现的那样,假设某种同构(即 隐含的操作上不相关的同构newtype)意味着莱布尼茨相等。这在 Haskell 98 中是正确的——但在 Haskell plus 扩展中根本不是这样。

也就是说,一个newtype提供了一对函数

a -> b
b -> a

没有做任何事情的核心,但不能得出结论

forall f. f a -> f b

因为f可能是类型函数或 GADT。这是需要的平等形式GeneralizedNewtypeDeriving

即使在 Haskell 98 中,它也打破了模块边界。你可以有类似的东西

class FromIntMap a where
  fromIntMap :: Map Int b -> Map a b

instance FromIntMap Int where
  fromIntMap = id

newtype WrapInt = WrapInt Int deriving FromIntMap

instance Ord WrapInt where
  WrapInt a <= WrapInt b = b <= a

这会做坏事...

我的博客文章展示了如何unsafeCoerce使用其他扩展(都是安全的)来实现几种方法,我GeneralizedNewtypeDeriving. 对现在的原因有了更好的理解,并且更有信心如果没有“System FC”风格的扩展(类型家族, GADT)。Sill,它是不安全的,如果有的话,应该小心使用。我的理解是 Lennart Augustsson(用户 augustss)在 hbc 中实现它的方式非常不同,而且这种实现是安全的。一个安全的实现会更受限制,也更复杂。GeneralizedNewtypeDerivingunsafeCoerce

更新:使用足够新的 GHC 版本(从 7.8.1 开始,所有问题都应该消失)GeneralizedNewtypeDeriving是安全的,因为新的角色系统

于 2013-06-16T21:03:24.190 回答