Haskell 中的 IORef
IORef in Haskell
我想知道 IORef 在 Haskell 中是否有合法的用法?更具体地说,如果有人可以解决以下问题或指向适当的地方以了解更多信息,我将不胜感激:
- 使用 IORef 被认为是一种不好的 Haskell 做法吗?如果是,为什么?更具体地说,它比 IO monad 好还是坏?
如果想向程序中添加状态,state monad 不是更好(更纯粹)的方法吗?如果一个人感觉更迫切,他不能仍然使用 STM 和 MVar,并且仍然更好吗?
是否存在可以使用 IORef 而不是 STM、MVar 或纯 IO 轻松处理的编程场景?
我正在阅读一篇使用 IORef 作为代码片段的论文,由于我对 IORef 的负面看法,我很难阅读它。与其沉迷于自己的无知,我认为向我的 Haskell 同事寻求帮助可能是一个更好的主意。
首先,我认为对于论文中的代码片段,使用 IORef
是非常明智的,特别是如果论文不是 about 可变的最佳实践引用或并发。 IORef
易于理解,具有直截了当的语法和语义(尤其是在非并发设置中),如果您希望 reader 专注于示例的其他方面而不是 IORef
秒。不幸的是,作者的方法适得其反——忽略 IORef
并注意论文的其余部分。
(如果论文 是 关于可变引用或并发的最佳实践,那么它可能是在更好的替代方案可用之前编写的。)
无论如何,对于更大的问题,反对使用 IORef
的主要理由是:
- 与将可变状态引入程序的任何其他机制一样,它使您的代码更难以推理、维护、测试等——函数式编程支持者会说的所有常见事情都会给 FP "edge" 超过突变密集型命令式算法。
- 它只是围绕专用
STRef RealWorld
的新型包装器,它在 STRef
上添加的唯一内容是一些原子操作。在非并发代码中,没有充分的理由不在 ST s
monad 中使用 STRef s
值,因为它们更灵活——您可以 运行 在纯代码中使用 runST
或者,如果需要,在 IO monad 中使用 stToIO
.
- 在并发代码中,有更强大的抽象,例如
MVar
和 STM
,它们比 IORef
更容易使用。
因此,在某种程度上可变状态是 "bad" 并且——如果你真的需要它——根据你是否需要并发,可以使用更好的替代方案,没有什么可推荐的IORef
.
另一方面, 如果您已经在 IO
monad 中处理一些非并发代码,因为您需要执行实际的 IO 操作,并且您真正需要一些不容易从 IO 中分离出来的普遍可变状态,那么使用 IORef
s 似乎是合法的。
关于您更具体的问题:
我想可以肯定地说,当 weaker tool would do the job 时,使用 IORef
被视为 "bad practice"。那个较弱的工具可能是 STRef s
,或者更好的是 State
monad,或者更好的是完全不需要任何状态的重写的高阶算法。因为 IORef
将 IO 与可变引用结合在一起,所以它是一种命令式的大锤,可能会导致可能出现最单一的 Haskell 代码,因此最好避免使用它,除非它是 "obviously" 正确的解决方案具体问题。
State
monad 通常是向程序添加状态的首选惯用方式,但它通过线程化一系列不可变状态来提供可变状态的 "illusion"通过计算得出的值,并不是所有的算法都可以通过这种方式有效地实现。在需要真正可变状态的地方,STRef
通常是非并发设置中的自然选择。请注意,您可能不会在非并发设置中使用 MVar
或 STM
—— 在这种情况下没有理由使用它们,它们会迫使您进入 IO
monad即使您不需要它。
是的,在某些编程场景中,IORef
或 STRef
优于 State
、STM
、MVar
,或纯 IO
(见下文)。很少有 IORef
明显优于 STRef
的情况,但是——如上所述——如果你已经在 IO
monad 中并且需要真正的可变状态,那就是与 IO 操作纠缠在一起,那么 IORef
可能在更简洁的语法方面比 STRef
有优势。
一些 IORef
或 STRef
是好的方法的例子:
base
包中的 Data.Unique
使用 IORef
作为生成唯一对象的全局计数器。
- 在
base
库中,文件句柄内部广泛使用 IORef
将缓冲区附加到句柄。这是 "already being in the IO monad with entangled IO operations". 的一个很好的例子
- 使用可变向量可以最有效地实现许多向量算法(例如,甚至像计算数据块中的字节频率这样简单的事情)。如果您使用
vector
包中的可变向量,那么从技术上讲,您使用的是可变字节数组而不是 STRef
或 IORef
,但它在道德上仍然是等价的。
equivalence
包使用 STRef
s 来有效地实现联合连接算法。
- 作为一个有点悬而未决的例子,如果您正在为一种命令式语言实现解释器,那么使用
IORef
或 STRef
可变变量的值通常是最有效率。
我想知道 IORef 在 Haskell 中是否有合法的用法?更具体地说,如果有人可以解决以下问题或指向适当的地方以了解更多信息,我将不胜感激:
- 使用 IORef 被认为是一种不好的 Haskell 做法吗?如果是,为什么?更具体地说,它比 IO monad 好还是坏?
如果想向程序中添加状态,state monad 不是更好(更纯粹)的方法吗?如果一个人感觉更迫切,他不能仍然使用 STM 和 MVar,并且仍然更好吗?
是否存在可以使用 IORef 而不是 STM、MVar 或纯 IO 轻松处理的编程场景?
我正在阅读一篇使用 IORef 作为代码片段的论文,由于我对 IORef 的负面看法,我很难阅读它。与其沉迷于自己的无知,我认为向我的 Haskell 同事寻求帮助可能是一个更好的主意。
首先,我认为对于论文中的代码片段,使用 IORef
是非常明智的,特别是如果论文不是 about 可变的最佳实践引用或并发。 IORef
易于理解,具有直截了当的语法和语义(尤其是在非并发设置中),如果您希望 reader 专注于示例的其他方面而不是 IORef
秒。不幸的是,作者的方法适得其反——忽略 IORef
并注意论文的其余部分。
(如果论文 是 关于可变引用或并发的最佳实践,那么它可能是在更好的替代方案可用之前编写的。)
无论如何,对于更大的问题,反对使用 IORef
的主要理由是:
- 与将可变状态引入程序的任何其他机制一样,它使您的代码更难以推理、维护、测试等——函数式编程支持者会说的所有常见事情都会给 FP "edge" 超过突变密集型命令式算法。
- 它只是围绕专用
STRef RealWorld
的新型包装器,它在STRef
上添加的唯一内容是一些原子操作。在非并发代码中,没有充分的理由不在ST s
monad 中使用STRef s
值,因为它们更灵活——您可以 运行 在纯代码中使用runST
或者,如果需要,在 IO monad 中使用stToIO
. - 在并发代码中,有更强大的抽象,例如
MVar
和STM
,它们比IORef
更容易使用。
因此,在某种程度上可变状态是 "bad" 并且——如果你真的需要它——根据你是否需要并发,可以使用更好的替代方案,没有什么可推荐的IORef
.
另一方面, 如果您已经在 IO
monad 中处理一些非并发代码,因为您需要执行实际的 IO 操作,并且您真正需要一些不容易从 IO 中分离出来的普遍可变状态,那么使用 IORef
s 似乎是合法的。
关于您更具体的问题:
我想可以肯定地说,当 weaker tool would do the job 时,使用
IORef
被视为 "bad practice"。那个较弱的工具可能是STRef s
,或者更好的是State
monad,或者更好的是完全不需要任何状态的重写的高阶算法。因为IORef
将 IO 与可变引用结合在一起,所以它是一种命令式的大锤,可能会导致可能出现最单一的 Haskell 代码,因此最好避免使用它,除非它是 "obviously" 正确的解决方案具体问题。State
monad 通常是向程序添加状态的首选惯用方式,但它通过线程化一系列不可变状态来提供可变状态的 "illusion"通过计算得出的值,并不是所有的算法都可以通过这种方式有效地实现。在需要真正可变状态的地方,STRef
通常是非并发设置中的自然选择。请注意,您可能不会在非并发设置中使用MVar
或STM
—— 在这种情况下没有理由使用它们,它们会迫使您进入IO
monad即使您不需要它。是的,在某些编程场景中,
IORef
或STRef
优于State
、STM
、MVar
,或纯IO
(见下文)。很少有IORef
明显优于STRef
的情况,但是——如上所述——如果你已经在IO
monad 中并且需要真正的可变状态,那就是与 IO 操作纠缠在一起,那么IORef
可能在更简洁的语法方面比STRef
有优势。
一些 IORef
或 STRef
是好的方法的例子:
Data.Unique
使用IORef
作为生成唯一对象的全局计数器。- 在
base
库中,文件句柄内部广泛使用IORef
将缓冲区附加到句柄。这是 "already being in the IO monad with entangled IO operations". 的一个很好的例子
- 使用可变向量可以最有效地实现许多向量算法(例如,甚至像计算数据块中的字节频率这样简单的事情)。如果您使用
vector
包中的可变向量,那么从技术上讲,您使用的是可变字节数组而不是STRef
或IORef
,但它在道德上仍然是等价的。 equivalence
包使用STRef
s 来有效地实现联合连接算法。- 作为一个有点悬而未决的例子,如果您正在为一种命令式语言实现解释器,那么使用
IORef
或STRef
可变变量的值通常是最有效率。
base
包中的