
(write r x >>= read) == (write r x >> return x) You probably mean (write r x >> read r) == (write r x >> return x)?
3) References are independent: If m does not refer to r, then: (read r >>= (\x -> m >> return x)) == m >> read r (write r x >> m) == m >>= (\v -> write r x >> return v) What if m writes to r' which is read by another thread, which in turn writes another value into r? What exactly does "does not refer to r" mean?
It's possible without unsafeCoerce if you add a Typeable constraint or pass a GADT type representation to new. Care to develop?
To be truly safe you need higher-rank types and use the same trick that ST does. Here I was, naively thinking I could put off learning about that for now ;)
But there's not much point; you may as well use ST. Not much *practical* point, I agree. I mostly asked out of curiosity.
Handling garbage collection is tricky, though. Can it even be done without compiler support?
-- Ariel J. Birnbaum