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