variables - State、ST、IORef 和 MVar 之间的区别

标签 variables haskell monads state-monad ioref

我正在处理Write Yourself a Scheme in 48 Hours (我已经完成了大约 85 小时)并且我已经完成了关于 Adding Variables and Assignments 的部分。本章中有一个很大的概念跳跃,我希望它是分两步完成的,中间有良好的重构,而不是直接跳到最终的解决方案。无论如何……

我迷失了许多似乎具有相同目的的不同类:StateSTIORefMVar。文中提到了前三个,而最后一个似乎是 StackOverflow 上有关前三个的许多问题的首选答案。它们似乎都在连续调用之间携带一种状态。

它们各自是什么以及它们之间有何不同?

<小时/>

特别是这些句子没有意义:

Instead, we use a feature called state threads, letting Haskell manage the aggregate state for us. This lets us treat mutable variables as we would in any other programming language, using functions to get or set variables.

The IORef module lets you use stateful variables within the IO monad.

所有这些都使得 type ENV = IORef [(String, IORef LispVal)] 行变得令人困惑 - 为什么是第二个 IORef?如果我改写 type ENV = State [(String, LispVal)] 会破坏什么?

最佳答案

状态 Monad:可变状态模型

State monad 是一个纯函数式环境,适用于具有状态的程序,具有简单的 API:

  • 获取

the mtl package 中的文档.

当在单个控制线程中需要状态时,通常使用状态单子(monad)。它在其实现中实际上并未使用可变状态。相反,程序由状态值参数化(即状态是所有计算的附加参数)。状态似乎只在单个线程中发生变化(并且不能在线程之间共享)。

ST monad 和 STRef

ST monad 是 IO monad 的受限制表亲。

它允许任意可变状态,实现为机器上的实际可变内存。该 API 在无副作用的程序中是安全的,因为 2 级类型参数可防止依赖于可变状态的值逃逸本地范围。

因此,它允许在其他纯程序中控制可变性。

通常用于可变数组和其他先发生变化然后卡住的数据结构。它也非常高效,因为可变状态是“硬件加速的”。

主要API:

  • Control.Monad.ST
  • runST——开始新的内存效应计算。
  • STRefs :指向(本地)可变单元格的指针。
  • 基于 ST 的数组(例如向量)也很常见。

将其视为 IO monad 危险性较小的兄弟。或者IO,只能读取和写入内存。

IORef:IO 中的 STRef

这些是 IO monad 中的 STRef(见上文)。它们没有与 STRef 相同的局部性安全保证。

MVar:带锁的 IORef

与 STRef 或 IORef 类似,但附加了锁,以便从多个线程进行安全的并发访问。仅当使用atomicModifyIORef(比较和交换原子操作)时,IORef 和 STRef 在多线程设置中才是安全的。 MVar 是一种更通用的安全共享可变状态的机制。

通常,在 Haskell 中,使用 MVar 或 TVar(基于 STM 的可变单元),而不是 STRef 或 IORef。

关于variables - State、ST、IORef 和 MVar 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5545517/

相关文章:

python - 使用类函数中的变量到其他函数中

arrays - Haskell 中的数组用类型(而不是数据)定义

haskell - 理解 Haskell 中 Monad 绑定(bind)运算符的关联性

jQuery 从数组中的每个值创建变量名称

java - 在 Java 中初始化非数字变量

java - JCombobox1与json数据转换静态变量

data-structures - 镜头、fclabels、数据访问器——哪个库用于结构访问和变异更好

haskell - 使用 ReaderT 创建可修改的环境

haskell - (>>=) 和 (>=>) 之间的区别

haskell - 有什么直觉可以理解在 Monad 中加入两个函数吗?