有时,如果没有至少一种语言扩展,我想写的一段代码是不合法的.当试图在研究论文中实现这些想法时尤其如此,这些论文倾向于使用在撰写论文时可用的任何spiffy,超扩展版本的GHC,而没有明确实际需要哪些扩展.
结果是我经常在我的.hs文件的顶部找到这样的东西:
{-# LANGUAGE TypeFamilies
, MultiParamTypeClasses
, FunctionalDependencies
, FlexibleContexts
, FlexibleInstances
, UndecidableInstances
, OverlappingInstances #-}
Run Code Online (Sandbox Code Playgroud)
我不介意,但我常常觉得我正在做出盲目的牺牲来安抚GHC的大神.它抱怨如果没有语言扩展X,某段代码无效,所以我为X添加了一个pragma.然后它要求我启用Y,所以我为Y添加了一个pragma.到这个结束时,我已经启用我不太了解的三个或四个语言扩展,我不知道哪些是"安全的".
用"安全"来解释我的意思:
我明白这UndecidableInstances是安全的,因为虽然它可能导致编译器不终止,只要代码编译它就不会有意想不到的副作用.
另一方面,OverlappingInstances显然是不安全的,因为它使我很容易意外地编写产生运行时错误的代码.
所以我的问题是:
是否有GHCextensions列表被认为是"安全的"并且"不安全"?
gla*_*erl 39
最好看一下SafeHaskell允许的内容:
安全的语言
安全语言(通过启用
-XSafe)以两种不同的方式限制事物:
- 某些GHC LANGUAGE扩展名不被完全禁止.
- 某些GHC LANGUAGE扩展功能受限.
以下是每个类别中的标志和扩展名:
- 完全不允许的:
GeneralizedNewtypeDeriving,TemplateHaskell- 受限功能:
OverlappingInstances,ForeignFunctionInterface,RULES,Data.Typeable
- 请参阅下面的限制功能
- 不重要:所有剩余的旗帜.
限制和禁用GHC Haskell功能
在安全语言方言中,我们限制以下Haskell语言功能:
ForeignFunctionInterface:这几乎是安全的,但是不允许导入具有非IO类型的函数的外部导入声明.所有FFI导入必须位于IO Monad中.RULES:由于它们可以以意想不到的方式改变可信代码的行为,违反语义一致性,因此它们在功能上受到限制.具体而言,删除RULES了M编译的模块中定义的任何内容-XSafe.RULES在可信赖的模块中定义,M导入仍然有效,并将照常启动.OverlappingInstances:此扩展可用于违反语义一致性,因为恶意代码可以通过更改导入不受信任模块的代码行为的方式重新定义类型实例(通过包含更具体的实例定义).对于M使用-XSafe但受限制编译的模块,不禁用扩展.虽然M可以定义重叠的实例声明,但它们只能用于M.如果在N导入的模块中M,在使用类型类函数的调用站点上,可以选择使用哪个实例(即重叠),最具体的选择来自M(或任何其他安全编译模块),则编译将失败.如果模块N被认为是安全的或可靠的或两者都不相关则无关紧要.Data.Typeable:我们允许Data.Typeable派生实例,但我们不允许手工制作的实例.派生的实例是由GHC生成的机器,应该是非常安全的,但是手工制作的实例可能与其类型有关,并允许类型之间的不安全强制.这符合SYB原创设计的精神.在安全语言方言中,我们完全禁用以下Haskell语言功能:
GeneralizedNewtypeDeriving:它可以用于违反构造函数访问控制,允许不受信任的代码以数据类型作者不想要的方式操作受保护的数据类型.即可以用来打破数据结构的不变量.TemplateHaskell:特别危险,因为即使在编译时它也可能导致副作用,并且可用于访问抽象数据类型.用TH打破模块边界非常容易.
我记得已经读过,FunctionalDependencies并且UndecidableInstances也可能是不安全的交互,因为除了允许无限的上下文堆栈深度UndecidableInstances也提升了所谓的覆盖条件(第7.6.3.2节),但我现在找不到这个.
编辑2015-10-27:自GHC获得类型角色支持以来,GeneralizedNewtypeDeriving不再是不安全的.(我不确定还有什么可能改变.)
| 归档时间: |
|
| 查看次数: |
2097 次 |
| 最近记录: |