readIORef 如何工作:创建副本还是不创建副本?
How does readIORef work: creates copy or it does not?
这段代码到底做了什么? someMap
是 myMap
引用的(::Data.Map.Strict.Map
的)对象的副本还是仅供参考?我的意思是在我用 readIORef
阅读后 someMap
可以更改 (通过另一个线程) 吗?像 C 的 volatile 之类的东西……这可能吗?我希望它是 copy/snapshot,所以任何更改都不会影响我的 someMap
,或者...?
do
....
someMap <- readIORef myMap
....
不,这不是副本。在Haskell中没有"copy"这样的东西,只有值,所有值都是不可变的。
IORef
包含一个值。 IORef
本身是可变的:您可以更改它包含的值。该值本身是不可变的。要理解这一点,请考虑当前包含 5
的 IORef Int
。如果你把那个值取出来然后加一得到 6
你就创建了一个新值,但是你没有把 5
的值突然变成 6
,因为这个值的 5
是不可变的。
同样,如果我创建一个值为 fromList [("foo", 5), ("bar, 6")]
的 Map
并将其放入 IORef,IORef 现在包含该值,但该值本身是不可变的。如果我取出值并使用 Map.insert
添加新条目,我创建了一个新值,而不是修改原始值,与上面的 5
和 6
完全相同。
希望这能回答您的问题。但是,您现在可能有另一个。如果所有的值都是不可变的,那么 IORefs 如何改变?
答案是IORef本身并没有改变。然而,IORef 作为一种通往我们称之为 "The Real World" 的可变的、不断变化的混乱的门户而存在。在现实世界中,你可以做同样的事情两次并得到不同的结果。这包括 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)
中写入了一些新值,那么,它确实如此。但它不会改变 在 切换之前已经从中提取的纯值。
有效代码有时间。具有不可变数据的纯引用透明代码是永恒的。
(真实的就是真实的,无论需要多长时间才能证明。)
这段代码到底做了什么? someMap
是 myMap
引用的(::Data.Map.Strict.Map
的)对象的副本还是仅供参考?我的意思是在我用 readIORef
阅读后 someMap
可以更改 (通过另一个线程) 吗?像 C 的 volatile 之类的东西……这可能吗?我希望它是 copy/snapshot,所以任何更改都不会影响我的 someMap
,或者...?
do
....
someMap <- readIORef myMap
....
不,这不是副本。在Haskell中没有"copy"这样的东西,只有值,所有值都是不可变的。
IORef
包含一个值。 IORef
本身是可变的:您可以更改它包含的值。该值本身是不可变的。要理解这一点,请考虑当前包含 5
的 IORef Int
。如果你把那个值取出来然后加一得到 6
你就创建了一个新值,但是你没有把 5
的值突然变成 6
,因为这个值的 5
是不可变的。
同样,如果我创建一个值为 fromList [("foo", 5), ("bar, 6")]
的 Map
并将其放入 IORef,IORef 现在包含该值,但该值本身是不可变的。如果我取出值并使用 Map.insert
添加新条目,我创建了一个新值,而不是修改原始值,与上面的 5
和 6
完全相同。
希望这能回答您的问题。但是,您现在可能有另一个。如果所有的值都是不可变的,那么 IORefs 如何改变?
答案是IORef本身并没有改变。然而,IORef 作为一种通往我们称之为 "The Real World" 的可变的、不断变化的混乱的门户而存在。在现实世界中,你可以做同样的事情两次并得到不同的结果。这包括 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)
中写入了一些新值,那么,它确实如此。但它不会改变 在 切换之前已经从中提取的纯值。
有效代码有时间。具有不可变数据的纯引用透明代码是永恒的。
(真实的就是真实的,无论需要多长时间才能证明。)