cli*_*ntm 6 monads haskell coding-style unsafe-perform-io
在工作中已经有一些关于将其作为禁止使用unsafePerformIO
和相关的部门范围政策的讨论.就个人而言,我并不介意,因为我一直认为,如果我发现自己想要使用它,通常意味着我需要重新思考我的方法.
这种限制听起来合理吗?我似乎记得在某个地方读到它主要是为了FFI,但是我不记得我现在读到的地方.
编辑:好的,那是我的错.它不会受到合理需要的限制,即.FFI.政策的重点更多是为了阻止懒惰和代码味道.
kee*_*gan 13
很多核心库就像在引擎盖下ByteString
使用unsafePerformIO
,例如自定义内存分配.
当您使用这样的库时,您相信库作者已证明其导出的API的引用透明性,并且记录了用户的任何必要前提条件.您的部门应该制定政策和审核流程,以便在内部进行类似的保证,而不是全面禁止.
C. *_*ann 12
嗯,有一些有效的用途unsafePerformIO
.它不仅仅是装饰性的,也不是测试你的美德的诱惑.但是,这些用途都不涉及为日常代码添加有意义的副作用.以下是一些可能被证明合理的用途示例,存在各种程度的怀疑:
包装内部不纯的函数,但没有外部可观察到的副作用.这与ST
monad的基本思想相同,不同之处在于程序员负担显示杂质不会"泄漏".
伪装一种故意以某种限制方式存在的功能.例如,只写杂质看起来与"从内部"的总纯度相同,因为没有办法观察产生的输出.这对于某些类型的日志记录或调试很有用,您可以明确地不希望IO
monad 需要一致性和明确定义的顺序.这方面的一个例子是Debug.Trace.trace
,我有时称之为unsafePerformPrintfDebugging
.
对纯计算的反思,产生纯粹的结果.一个典型的例子就是明确的选择运算符,它可以并行运行两个等效的纯函数,以便更快地得到答案.
内部无法观察到的引用透明度的破坏,例如在初始化数据时引入非确定性.只要每个impure函数只被评估一次,就会在程序的任何单次运行期间有效地保留引用透明度,即使使用相同参数调用的相同的faux-pure函数在不同的运行中给出不同的结果.
关于上述所有内容的重要注意事项是所产生的杂质受到严格控制并且范围有限.鉴于控制副作用的细粒度系统比通用IO
monad 更精细,这些都是切割半纯度的明显候选者,就像上述ST
monad中的受控可变状态一样.
后脚本:如果unsafePerformIO
正在考虑针对任何非必要用途的强硬立场,我强烈建议将禁止范围扩大到包含unsafeInterleaveIO
和允许观察其行为的任何功能.unsafePerformIO
如果你问我,它至少和我上面列举的一些例子一样粗略.
unsafePerformIO是IO monad的runST.它有时是必不可少的.但是,与runST不同,编译器无法检查您是否保留了引用透明性.
因此,如果您使用它,程序员有责任解释为什么使用是安全的.它不应该被禁止,它应该附有证据.