首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >哈斯克尔的IORef

哈斯克尔的IORef
EN

Stack Overflow用户
提问于 2018-09-23 16:13:21
回答 1查看 2.8K关注 0票数 14

我想知道在哈斯克尔是否有合法的使用IORef?更具体地说,如果有人能回答以下问题或指出一个适当的地方了解更多这方面的情况,我将非常感激:

  1. 使用IORef被认为是一种糟糕的Haskell实践吗?如果是,为什么?更确切地说,它比IO单片更好还是更糟?
  2. 如果一个人想把状态添加到一个程序中,那么state不是一种更好(更纯粹)的方法吗?如果一个人感到更迫切,难道他就不能继续使用STM和MVar,并且仍然过得更好吗?
  3. 是否有使用IORefs而不是STM、MVar或纯IO轻松处理的编程场景?

我正在阅读一篇使用IORef作为代码片段的论文,由于我对IORef的负面看法,它对我来说一直很难阅读。与其沉溺于我的无知之中,我认为向哈斯克勒同胞寻求帮助也许是个更好的主意。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-23 20:12:59

首先,我认为对于论文中的代码片段来说,使用IORef是非常明智的,特别是如果本文不是关于可变引用或并发的最佳实践的话。IORef很容易理解,语法和语义都很简单(特别是在非并发设置中),如果您希望读者专注于IORef以外的示例,这是一种自然的选择。不幸的是,作者的方法对您来说适得其反--只需忽略IORef,关注论文的其余内容。

(如果这篇论文是关于可变引用或并发性的最佳实践的话,那么它也许是在获得更好的替代方案之前编写的。)

无论如何,对于您更大的问题,使用IORef的主要反对意见是:

  • 就像在程序中引入可变状态的任何其他机制一样,它使您的代码更难推理、维护、测试等等--所有函数编程的支持者通常会说,FP比突变密集型的命令式算法具有“优势”。
  • 它只是一个专门的STRef RealWorld的新类型包装器,它在STRef上添加的唯一东西就是一些原子操作。在非并发代码中,没有充分的理由不在ST s monad中使用ST s值,因为它们更灵活--您可以使用runST运行它们,如果需要,也可以在带有stToIO的IO monad中运行它们。
  • 在并发代码中,有更强大的抽象,比如MVarSTM,它们比IORef的更容易使用。

因此,在可变状态是“坏”的程度上--如果您真的需要它--根据您是否需要并发性,可以获得更好的替代方案,因此没有什么可推荐的IORef

另一方面, --如果您已经在IO monad中处理一些非并发代码,因为您需要执行实际的IO操作,并且您确实需要一些不容易与IO分离的普遍的可变状态,那么使用IORef似乎是合法的。

关于你更具体的问题:

  1. 我想可以肯定地说,当使用IORef时,weaker tool would do the job被认为是“不好的实践”。这个较弱的工具可能是一个STRef s,或者更好的是一个State单块,或者更好的一个重写的高阶算法,它根本不需要任何状态。因为IORef将IO与可变引用结合在一起,这是一种命令式的大锤,可能会导致最统一的Haskell代码,因此,除非它“显然”是解决特定问题的正确解决方案,否则最好避免它。
  2. State monad通常是向程序添加状态的首选惯用方法,但它通过通过计算线程处理一系列不变的状态值来提供可变状态的“错觉”,而且并不是所有的算法都能以这种方式有效地实现。当需要真正的可变状态时,STRef通常是非并发设置中的自然选择。请注意,您可能不会在非并发设置中使用MVarSTM --在本例中没有使用它们的理由,而且即使您不需要它们,它们也会强迫您进入IO monad。
  3. 是的,在一些编程场景中,IORefSTRef都优于StateSTMMVar或纯IO (见下文)。有几种情况下,IORef显然比STRef更可取,但是--正如上面提到的--如果您已经处于IO monad中,并且需要与IO操作纠缠在一起的真正的可变状态,那么IORef在语法上可能比STRef有优势。

一些例子说明了IORefSTRef是一种很好的方法:

  • Data.Uniquebase包中使用IORef作为生成唯一对象的全局计数器。
  • base库中,文件句柄内部广泛使用IORefs将缓冲区附加到句柄。这是一个很好的例子,“已经在IO单与纠缠的IO操作”。
  • 许多向量算法使用可变向量(例如,甚至像计算数据块中的字节频率这样简单的东西)最有效地实现。如果您使用来自vector包的可变向量,那么从技术上讲,您使用的是可变字节数组,而不是STRefIORef,但在道义上仍然是等价的。
  • equivalence包使用STRefs来高效地实现联合连接算法。
  • 例如,如果您要为命令式语言实现一个解释器,那么对可变变量使用IORefSTRef值通常是最有效的。
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52467957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档