use*_*465 6 monads haskell ioref
我想知道Haskell中的IORef是否合法使用?更具体地说,如果有人能够解决以下问题或指向适当的地方了解更多信息,我将感激不尽:
如果有人想要在程序中添加状态,那么状态monad不是更好(更纯粹)的方式.如果一个人感觉更加迫切,他还不能继续使用STM和MVar,还能更好吗?
是否有使用IORef而不是STM,MVar或纯IO轻松处理的编程方案?
我正在阅读一篇使用IORef作为代码片段的论文,由于我对IORef的负面看法,我很难读到这篇论文.我不想沉迷于我的无知,而是想让我的同伴Haskellers寻求帮助可能是一个更好的主意.
首先,我认为对于论文中的代码片段,使用IORef是非常明智的,特别是如果论文不是关于可变引用或并发的最佳实践. IORef很容易理解,具有直接的语法和语义(特别是在非并发设置中),如果您希望读者专注于除了IORefs 之外的示例的各个方面,这是一个自然的选择.令人遗憾的是,作者的方法已经适合你了 - 只要忽略它IORef并注意论文的其余内容.
(如果该论文是关于可变引用或并发性的最佳实践,也许它是在更好的替代方案可用之前编写的.)
无论如何,对于你的大问题,使用的主要反对意见IORef是:
STRef RealWorld,它唯一添加的STRef是一些原子操作.在非并发代码中,没有充分的理由不在monad中使用STRef s值ST s,因为它们更灵活 - 您可以在纯代码中运行它们runST,如果需要,可以在IO monad中运行它们stToIO.MVar和STM,更容易比上班IORef秒.所以,在可变状态是"坏"的情况下 - 如果你真的需要它 - 根据你是否需要并发性,可以使用更好的替代方案,没有太多建议IORef.
另一方面,如果你已经在IOmonad中处理一些非并发代码,因为你需要执行实际的IO操作,并且你真的需要一些不容易从IO解开的普遍可变状态,那么使用IORefs看似合法.
关于您更具体的问题:
我想可以肯定地说,IORef当一个较弱的工具能够完成工作时,使用被认为是"不好的做法" .那个较弱的工具可能是一个STRef s或更好的Statemonad或更好的重写高阶算法,根本不需要任何状态.因为IORefIO与可变引用相结合,所以它是一种必要的大锤,可能会导致最单一的Haskell代码成为可能,所以最好避免它,除非它"显然"是针对特定问题的正确解决方案.
该State单子通常是添加状态到程序的优选的惯用方式,但它通过计算线程不可变状态值的序列提供了一个可变状态的"幻象",并且不是所有的算法可以高效地实现这种方式.在需要真正的可变状态的情况下,a STRef通常是非并发设置中的自然选择.请注意,您可能不会使用MVar或STM在非并发设置中 - 在这种情况下没有理由使用它们,IO即使您不需要它也会强制您进入monad.
是的,有被编程场景,其中任一IORef或STRef优于State,STM,MVar,或纯IO(见下文).很少有情况IORef显然是优选的STRef,但是 - 如上所述 - 如果你已经在IOmonad中并且需要与IO操作纠缠在一起的真正可变状态,那么IORef可能STRef在略微方面有优势清洁语法.
一些例子IORef或者STRef是一种好方法:
Data.Unique在base包中使用IORef一个全局计数器来生成唯一对象.base库中,文件句柄内部广泛使用IORefs来将缓冲区附加到句柄.这是"已经在IO monad中进行纠缠IO操作"的一个很好的例子.vector包中的可变向量,那么从技术上讲,您使用的是可变字节数组而不是STRef或者IORef,但它仍然在道德上等效.equivalence软件包使用STRefs来有效实现union-join算法.IORef或STRef变量变量值通常会是最有效的.