这段代码到底是做什么的?someMap
是myMap
引用的对象(::Data.Map.Strict.Map
)的副本,还是仅供参考?我的意思是someMap
在我用readIORef
阅读后可以更改(通过另一个线程)吗?类似于 C 的易变性...可能吗?我希望它是复制/快照,所以任何更改都不会影响我的someMap
,或者......?
do
....
someMap <- readIORef myMap
....
不,它不是副本。在Haskell中,没有"副本"这样的东西,只有值,所有值都是不可变的。
IORef
包含一个值。IORef
本身是可变的:您可以更改它包含的值。值本身是不可变的。要理解这一点,请考虑当前包含5
的IORef Int
。如果你得到这个值并添加一个值来得到6
你已经创建了一个新值,但你没有将5
值更改为突然变得6
,因为5
的值是不可变的。
同样,如果我使用值fromList [("foo", 5), ("bar, 6")]
创建一个Map
并将其放入 IORef 中,IORef 现在包含该值,但值本身是不可变的。如果我取出值并使用Map.insert
添加一个新条目,则我创建了一个新值,而不是修改原始值,与上面的5
和6
完全相同。
希望这能回答你的问题。但是,您现在可能还有另一个。如果所有值都是不可变的,IORefs 如何更改?
答案是 IORef 本身不会改变。然而,IORefs 作为一种门户存在,通往我们称之为"现实世界"的可变不断变化的混沌。在现实世界中,你可以做同样的事情两次,得到不同的结果。这包括readLine
和readIORef
。IO monad 的存在是为了隔离这种混乱,同时仍然允许程序与之交互。因此,每个与 IORefs 一起使用的函数都在 IO monad 中。
readIORef :: IORef a -> IO a
,所以myMap
必须IORef a
和readIORef myMap :: IO a
。
所以someMap :: a
,因为它在IO a
类型的do
代码行中<-
的左侧(它总是a <- M a
,do
表示法)。
在您的情况下,该a ~ Data.Map.Strict.Map k v
,即纯不可变值。
如果另一个线程将一些新值写入该myMap :: IORef (Data.Map.Strict.Map k v)
,那么它确实如此。但它不会改变在切换之前已经从中抽取的纯值。
有效的代码是有时间的。具有不可变数据的纯引用透明代码是永恒的。
(什么是真的,就是真的,不管需要多长时间来证明它。