我应该默认使用Haskell模块吗?

Bar*_*icz 5 haskell ghc

标记模块有什么缺点Safe吗?它应该是假定的默认值吗?

typ*_*ris 6

正如您可以在GHC用户手册中阅读的那样,如果您标记模块Safe,则只能使用Haskell语言的某个"安全"子集.

  1. 您只能导入也标记的模块Safe(排除函数unsafeCoerce或者unsafePerformIO).
  2. 您不能使用Template Haskell.
  3. 你不能在外面使用FFI IO.
  4. 你不能使用GeneralisedNewtypeDeriving.
  5. 您无法Generic为模块中定义的类型手动实现类型类.
  6. 等等

作为交换,该模块的用户获得了一系列保证(引自手册):

  • 参照透明度 - 可以信任类型.任何纯粹的功能,都保证是纯粹的.评估它们是确定性的,不会引起任何副作用.IOmonad中的函数仍然允许并且像往常一样运行.因此,例如,unsafePerformIO :: IO a -> a在安全语言中不允许使用该函数来强制执行此属性.
  • 模块边界控制 - 只能通过安全语言访问通过其他模块导出列表公开提供的符号.使用未由定义模块导出的数据构造函数的值无法检查或创建.因此,如果模块M 通过仔细使用其导出列表来建立一些不变量,那么使用安全语言编写的导入代码M将保证遵守这些不变量.
  • 语义一致性 - 对于导入以安全语言编写的模块的任何模块,使用和不使用安全导入进行编译的表达式在两种情况下都具有相同的含义.也就是说,导入用安全语言编写的模块不能改变不依赖于该模块的现有代码的含义.因此,例如,对使用有一些限制 OverlappingInstances,因为这些可能违反此属性.
  • 严格的子集 - 安全语言严格地是GHC实现的Haskell的子集.任何以安全语言编译的表达式都与在普通Haskell中编译时具有相同的含义.

请注意,安全性是推断的.如果你的模块没有任何的标记Safe,Trustworthy或者Unsafe,GHC会推断模块与安全SafeUnsafe.设置Safe标志时,如果GHC确定模块实际上不安全,则会发出错误.您还可以设置-Wunsafe,如果推断模块不安全,则会发出警告.如果您推断,即使您的依赖项的安全状态发生更改,您的模块也将继续编译.如果你写出来,你向用户保证安全状态是稳定可靠的.

本手册中描述的一个用例是指运行"不受信任"的代码.如果您在产品中提供任何类型的扩展点,并且您希望确保这些功能不会用于攻击您的产品,则可以要求标记扩展点的代码Safe.

您可以标记模块Trustworthy,这在实施模块时不会以任何方式限制您.您的模块可能会从Safe代码中使用,您有责任不违反保证,应由Safe代码提供.所以这是一个承诺,你是所述模块的作者,给予.您可以使用该标志-fpackage-trust在编译标记为此处Trustworthy所述的模块时启用额外检查.

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

  • 为了清晰起见,我已经编辑了答案,但是我想添加(我没有编辑它,因为我认为这是意义上的重大改变),同时通常会推断出"安全"和"不安全".好吧,有些图书馆应该宣称自己是"值得信赖的".在库中使用时,"Safe"和"Unsafe"表示"此模块导出的API安全/不安全".`Trustworthy`意味着"导出的API是安全的,但实现不是." 库可能不会直接在"安全"上下文中使用,但是它的用户可能是,所以应该很好并标记其安全的API,以便让这些用户使用它. (2认同)