是否有被认为“安全”的GHC扩展名列表?
偶尔,如果没有至少一种语言扩展名,我想写的一段代码是不合法的。 当试图在研究论文中实现想法时尤其如此,在撰写论文时可以使用GHC的任何漂亮的超扩展版本,而没有明确说明哪些扩展实际需要。
结果是,我经常在我的.hs文件的顶部得到类似这样的东西:
{-# LANGUAGE TypeFamilies
, MultiParamTypeClasses
, FunctionalDependencies
, FlexibleContexts
, FlexibleInstances
, UndecidableInstances
, OverlappingInstances #-}
我不介意,但我常常觉得好像我为了安抚GHC的伟大上帝而盲目牺牲。 它抱怨说,如果没有语言扩展X,某段代码是无效的,所以我为X添加了一个编译指示。然后它要求我启用Y,因此我为Y添加了一个编译指示。到此结束时,我已经启用三个或四个我不太了解的语言扩展,我不知道哪些是'安全'的。
解释我的意思是“安全”:
我明白, UndecidableInstances
是安全的,因为尽管它可能会导致编译器不终止,只要代码编译它不会有意想不到的副作用。
另一方面, OverlappingInstances
显然是不安全的,因为它使我很容易意外地编写出现运行时错误的代码。
所以我的问题是:
是否有GHCextensions列表被认为是“安全的”,哪些是“不安全的”?
最好看看SafeHaskell允许的内容:
安全的语言
安全语言(通过-XSafe
启用)以两种不同的方式限制事物:
下面是正确的标志和扩展属于每个类别:
GeneralizedNewtypeDeriving
, TemplateHaskell
OverlappingInstances
, ForeignFunctionInterface
, RULES
, Data.Typeable
限制和禁用GHC Haskell功能
在安全语言方言中,我们限制以下Haskell语言功能:
ForeignFunctionInterface
:这是非常安全的,但不允许导入带有非IO类型函数的外部导入声明。 所有FFI导入都必须驻留在IO Monad中。 RULES
:由于它们可以以意想不到的方式改变可信代码的行为,违反语义一致性,它们在功能上受到限制。 具体来说,删除用-XSafe
编译的模块M
定义的任何RULES
。 在可信任的模块中定义的R RULES
M
进口仍然有效,并将照常进行。 OverlappingInstances
:这个扩展可以用来违反语义一致性,因为恶意代码可以通过改变导入不可信模块的代码行为的方式来重新定义一个类型实例(通过包含更具体的实例定义)。 对于使用-XSafe
编译但受限制的模块M
,扩展未禁用。 虽然M
可以定义重叠的实例声明,但它们只能在M
。 如果在导入M
的模块N
中,在使用类型函数的调用站点中,可以选择使用哪个实例(即重叠),最具体的选择来自M
(或任何其他安全编译模块),那么编译将失败。 如果模块N
被认为是安全的或者可信的或者两者都不是,则不相关。 Data.Typeable
:我们允许派生Data.Typeable
实例,但我们不允许手工制作实例。 衍生的实例是由GHC生成的机器,应该是完全安全的,但手工制作的实例可以说谎它们的类型,并允许不同类型之间的不安全强制。 这符合SYB原创设计的精神。 在安全语言方言中,我们完全禁用以下Haskell语言功能:
GeneralizedNewtypeDeriving
:通过允许不可信的代码以数据类型作者不打算的方式操纵受保护的数据类型,它可以用于违反构造函数访问控制。 即可以用来打破数据结构的不变量。 TemplateHaskell
:特别危险,因为它甚至可以在编译时引起副作用,并可用于访问抽象数据类型。 用TH打破模块边界很容易。 我记得曾经阅读过FunctionalDependencies
和UndecidableInstances
的交互也可能是不安全的,因为除了允许无限的上下文栈深度UndecidableInstances
也提升所谓的覆盖条件(见第7.6.3.2节),但我找不到这个引用在这一刻。
编辑2015-10-27:自从GHC获得类型角色的支持后, GeneralizedNewtypeDeriving
不再不安全。 (我不确定还有什么可能会改变。)
上一篇: Is there a list of GHC extensions that are considered 'safe'?
下一篇: Possible optimizations in Haskell that are not yet implemented in GHC?