readIORef 如何工作:创建副本还是不创建副本?

How does readIORef work: creates copy or it does not?

这段代码到底做了什么? someMapmyMap 引用的(::Data.Map.Strict.Map 的)对象的副本还是仅供参考?我的意思是在我用 readIORef 阅读后 someMap 可以更改 (通过另一个线程) 吗?像 C 的 volatile 之类的东西……这可能吗?我希望它是 copy/snapshot,所以任何更改都不会影响我的 someMap,或者...?

     do
        ....
        someMap <- readIORef myMap
        ....

不,这不是副本。在Haskell中没有"copy"这样的东西,只有值,所有值都是不可变的。

IORef 包含一个值。 IORef 本身是可变的:您可以更改它包含的值。该值本身是不可变的。要理解这一点,请考虑当前包含 5IORef Int。如果你把那个值取出来然后加一得到 6 你就创建了一个新值,但是你没有把 5 的值突然变成 6,因为这个值的 5 是不可变的。

同样,如果我创建一个值为 fromList [("foo", 5), ("bar, 6")]Map 并将其放入 IORef,IORef 现在包含该值,但该值本身是不可变的。如果我取出值并使用 Map.insert 添加新条目,我创建了一个新值,而不是修改原始值,与上面的 56 完全相同。

希望这能回答您的问题。但是,您现在可能有另一个。如果所有的值都是不可变的,那么 IORefs 如何改变?

答案是IORef本身并没有改变。然而,IORef 作为一种通往我们称之为 "The Real World" 的可变的、不断变化的混乱的门户而存在。在现实世界中,你可以做同样的事情两次并得到不同的结果。这包括 readLinereadIORef。 IO monad 的存在是为了隔离这种混乱,同时仍然允许程序与之交互。因此,每个与 IORefs 一起工作的函数都在 IO monad 中。

readIORef :: IORef a -> IO a,所以myMap一定是IORef areadIORef myMap :: IO a

所以 someMap :: a,因为它位于类型 IO ado 代码行中 <- 的左侧(它总是 a <- M a, , 在 do 表示法中)。

在你的例子中,a ~ Data.Map.Strict.Map k v,即一个纯粹的不可变值。

如果另一个线程向那个 myMap :: IORef (Data.Map.Strict.Map k v) 中写入了一些新值,那么,它确实如此。但它不会改变 切换之前已经从中提取的纯值。

有效代码有时间。具有不可变数据的纯引用透明代码是永恒的。

(真实的就是真实的,无论需要多长时间才能证明。)