I found some sample code, and changed it a little
counter = unsafePerform $ newIORef 0
newNode _ = unsafePerformIO $
do
i <- readIORef counter
writeIORef counter (i+1)
return i
Which returns 1 then 2 then 3 then 3 etc each time it's run.
But when I change it to
newNode = unsafePerformIO $
do
i <- readIORef counter
writeIORef counter (i+1)
return i
then I get 0 every time I run it.
Why is this happening, and what can I do to fix it?
In your second version newNode
is a simple value, not a function. So haskell evaluates it exactly once and then gives you the result of that evaluation whenever you access newNode
.
A word of warning: Using unsafePerformIO
on anything other than an IO action which you know to be referentially transparent is dangerous. It might interact badly with some optimizations and just generally not behave like you expect. There's a reason it's got the word "unsafe" in its name.
As a way to play around with unsafePerformIO
your code is fine, but if you ever want to use something like it in real code, I'd strongly encourage you to reconsider.