No it is not a copy. In Haskell there is no such thing as a "copy", there are only values and all values are immutable.
An IORef
contains a value. The IORef
itself is mutable: you can change the value that it contains. The value itself is not mutable. To understand this, think of an IORef Int
which currently contains 5
. If you get that value out and add one to it to get 6
you have created a new value, but you have not changed the 5
value to have suddenly become 6
, because the value of 5
is immutable.
Likewise if I create a Map
with the value fromList [("foo", 5), ("bar, 6")]
and put it in an IORef, the IORef now contains that value, but the value itself is immutable. If I get the value out and add a new entry using Map.insert
I have created a new value, not modified the original value, exactly the same way as with the 5
and 6
above.
Hopefully that answers your question. However you may now have another one. If all values are immutable, how can IORefs change?
The answer is that the IORef itself does not change. However IORefs exist as a kind of portal to the mutable ever-changing chaos that we call "The Real World". In The Real World you can do the same thing twice and get different results. That includes readLine
and readIORef
. The IO monad exists to quarantine this chaos while still allowing the program to interact with it. Hence every function that works with IORefs is in the IO monad.