Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell readIORef如何工作:创建副本还是不创建副本?_Haskell_Immutability_Io Monad_Do Notation_Ioref - Fatal编程技术网

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

Haskell readIORef如何工作:创建副本还是不创建副本?,haskell,immutability,io-monad,do-notation,ioref,Haskell,Immutability,Io Monad,Do Notation,Ioref,这段代码到底是做什么的?someMap是myMap引用的对象(属于::Data.Map.Strict.Map)的副本还是仅作为参考?我的意思是,在我用readIORef阅读后,是否可以someMap更改(通过另一个线程)?有点像C的挥发性。。。可能吗?我希望它是复制/快照,所以任何更改都不会影响我的someMap,或者 do .... someMap不,它不是副本。在Haskell中没有“复制”这类东西,只有值,所有值都是不可变的 IORef包含一个值。IORef本身是可变的:您可以更改它包含的

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

do
....

someMap不,它不是副本。在Haskell中没有“复制”这类东西,只有值,所有值都是不可变的

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

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

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


答案是IORef本身不会改变。然而,IOREF是一种通向我们称之为“真实世界”的变化无常的混乱的门户。在现实世界中,你可以做同样的事情两次,得到不同的结果。这包括
readLine
readIORef
。IO单子的存在是为了隔离这种混乱,同时仍然允许程序与之交互。因此,使用IORefs的每个函数都在IO单子中。

readIORef::IORef a->IO a
,因此
myMap
必须是
IORef a
readIORef myMap::IO a


所以
someMap::a
,因为它在
的左边是的,当然是这样,但问题是:如果我的线程a使用
readIORef
读取映射,并且我正在使用它做一些事情,那么它能被另一个线程B更改吗?据我所知,Haskell在编写时会进行复制,而且IO monad是好的类C代码的唯一包装器(readIORef/WriteOref甚至可以像C中一样重新排序),因此:
someMap
可以在我读过它之后被另一个线程更改吗?@Paul AG:不,因为如果使用
WriteOref
,您会向引用写入不同的值。数据结构永远不会被修改,您将创建一个“浅”修改副本。因此,如果您写入
IORef
,则意味着您现在让ref指向一个不同的映射。@Paul AG我认为您试图通过理解Haskell如何转换为内存上的低级操作来理解它的语义。这对于命令式语言(如C语言或C++语言,甚至java)都适用,因为这些语言的底层程序员模型是冯诺依曼体系结构。它不适用于Haskell,因为Haskell的底层程序员模型是lambda演算。因此,你不应该试图从指针和副本的角度来思考Haskell语义,而应该试着从值和函数的角度来思考。尽管这个特殊的例子很容易用指针和副本的类比来解释。IORef我想要一个包含指向不可变对象指针的可变变量。读取指针是原子性的,所以当我读取指针时,另一个线程不可能写入指针。一旦我阅读了它以找出指向的对象,其他线程做什么并不重要;它们无法更改我现在使用的不可变对象,因此它们只能在我再次读取指针时影响我。