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



这段代码到底是做什么的?someMapmyMap引用的对象(::Data.Map.Strict.Map)的副本,还是仅供参考?我的意思是someMap在我用readIORef阅读后可以更改(通过另一个线程)吗?类似于 C 的易变性...可能吗?我希望它是复制/快照,所以任何更改都不会影响我的someMap,或者......?

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

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

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

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

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

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

readIORef :: IORef a -> IO a,所以myMap必须IORef areadIORef myMap :: IO a

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

在您的情况下,该a ~ Data.Map.Strict.Map k v,即纯不可变值。

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

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

(什么是真的,就是真的,不管需要多长时间来证明它。

最新更新