默认情况下,我应该使Haskell模块安全吗?

时间:2018-10-03 18:12:11

标签: haskell ghc

标记模块Safe是否有不利之处?应该是默认值吗?

1 个答案:

答案 0 :(得分:6)

您可以在GHC user manual中阅读,如果您标记模块Safe,则只能使用Haskell语言的某个“安全”子集。

  1. 您只能导入也标记为Safe的模块(排除了unsafeCoerceunsafePerformIO之类的功能)。
  2. 您不能使用模板Haskell。
  3. 您不能在IO之外使用FFI。
  4. 您不能使用GeneralisedNewtypeDeriving
  5. 您无法为在模块中定义的类型手动实现Generic类型类。

作为交换,模块的用户获得了很多保证(从手册中引用):

  
      
  • 引用透明性-可以信任的类型。任何纯函数,都保证是纯函数。评估它们是确定性的   并且不会造成任何副作用。 IO monad中的功能仍然   允许并像往常一样表现。因此,例如,unsafePerformIO :: IO a -> a函数在安全语言中是不允许执行的   财产。
  •   
  • 模块边界控制-只有在其他模块导出列表中公开可用的符号才能在保险箱中访问   语言。使用未由定义导出的数据构造函数的值   模块,无法检查或创建。因此,如果模块M   通过谨慎使用其导出列表来确定一些不变式,   然后保证以安全的语言编写的代码导入M   尊重那些不变性。
  •   
  • 语义一致性-对于导入以安全语言编写的模块的任何模块,使用和不使用编译的表达式   在两种情况下,安全导入的含义相同。那是,   导入以安全语言编写的模块无法更改   不依赖于该模块的现有代码的含义。因此对于   例如,在使用上有一些限制   OverlappingInstances,因为它们可能会违反此属性。
  •   
  • 严格的子集-安全语言严格来说是GHC实施的Haskell的子集。使用安全语言编译的任何表达式   与在普通的Haskell中进行编译的含义相同。
  •   

请注意,可以推断出安全性。如果您的模块未标记有SafeTrustworthyUnsafe中的任何一个,则GHC会将模块的安全性推断为SafeUnsafe。当您设置Safe标志时,如果GHC认为模块实际上并不安全,它将发出一个错误。您还可以设置-Wunsafe,如果推断出模块不安全,则会发出警告。如果您推断出它,即使您的依赖项的安全状态发生了变化,您的模块也将继续编译。如果将其写出,则向用户保证安全状态稳定可靠。

手册中描述的一个用例是运行“不受信任”的代码。如果您在产品中提供了任何种类的扩展点,并且要确保不使用这些功能来攻击产品,则可以要求将扩展点的代码标记为Safe

您可以标记模块Trustworthy,这在实现模块时不会以任何方式限制您。然后可以从Safe代码中使用您的模块,并且您有责任不违反保证,而该保证应由Safe代码给出。所以,这是一个承诺,您是上述模块的作者,应该给予。在编译here中描述为标记为-fpackage-trust的模块时,可以使用标志Trustworthy启用额外的检查。

因此,如果您编写普通的库并且没有充分的理由关心Safe Haskell,那么您可能就不需要关心。如果您的模块是安全的,那很好,可以推断出来。如果不是,那么这可能是有原因的,例如因为您使用了unsafePerformIO,这也很好。如果您知道您的模块将以某种要求其在-XSafe下进行编译的方式使用(例如,如上所述的插件),则应该这样做。在其他所有情况下,请不要打扰。