I'm trying to understand how an IORef (MVar, TVar) might be shared between separate instances of function closures. I've defined a function `count` that returns a function with an IORef "inside",
count :: IORef Int -> Int -> IO (Char -> IO Int) count io i = do writeIORef io i return (\c -> if c == 'a' then modifyIORef io (+1) >> readIORef io else readIORef io)
Now I define an IORef and a couple of counters that share the IORef,
iio :: IO (IORef Int) iio = newIORef 0 ic1 = do { io <- iio ; count io 0 } ic2 = do { io <- iio ; count io 0 }
I expected to see the counters sharing the IORef, so that executing `counter1` below would print "1,1,2,3". Instead, it prints "1,0,1,2".
counter1 = do c1 <- ic1 c2 <- ic2 c1 'a' >>= print c2 'b' >>= print c2 'a' >>= print c1 'a' >>= print
However, if I create the two counters inside the same do block, I get the result I expected, "1,1,2,3".
counter2 = do io <- iio c1 <- count io 0 c2 <- count io 0 c1 'a' >>= print c2 'b' >>= print c2 'a' >>= print c1 'a' >>= print
So apparently my mental picture of an IORef as a pointer to a value is wrong. I need a new mental picture. What's going on here? Thanks, -Rod