External Publication
Visit Post

Haskell's missing mutable reference type

Haskell Community [Unofficial] June 14, 2026
Source

OK, this is supposed to be clear from loggerExampleConcurrently. I’ll see if I can clarify that.

In that example you do the modification inside the fork, so it wasn’t obvious to me whether the modification would be visible if you did it the other way around.

How would the behaviour differ? Do you mean that InheritedThreadLocalIORef could be modified within a thread like an IORef?

Yes. You modify it just like an IORef, it’s just that such a modification is visible to a) your current thread, and b) child threads (if it happens before you fork the thread). That is, exactly how masking state works today.

I just don’t like the semantics of the latter. It would allow you to observe whether you’re running in a forked thread. See “the interaction between the semantics of thread creation and of IOScopedRef are good” in the Concurrency section.

I don’t understand how it would do that, can you give an example?

What’s the use of having thread local state that allows non-scoped modifications?

What’s a “non-scoped modification”? Do you mean writeIORef versus withModifiedIORef :: IORef a -> (a -> a) -> IO a -> IO a? People seem to be perfectly happy with the non-scoped modification functions on IORef, and you can implement the scoped ones with it if you want?

The point of having thread-local state is: modifications in child threads don’t affect the parent or sibling threads.

The point of having inherited thread-local state is: forked code “continues” from the parent context in a natural way.

The problems you observe in fork-fragile-reader-like-operations seem to me to be related to these two things. I’m arguing that the “scoped” part of it is perhaps not the crux!

Discussion in the ATmosphere

Loading comments...