Hi,
I'm trying to get MonadReader-like functionality in the IO monad. It
doesn't appear possible implement it with the interfaces that
Haskell98 or GHC provide. I'm looking for something like "thread-local
variables". The interface could be something like this:
newTLRef :: a -> IO (TLRef a)
withTLRef :: TLRef a -> a -> IO b -> IO b
readTLRef :: TLRef a -> IO a
writeTLRef :: TLRef a -> a -> IO ()
modifyTLRef :: TLRef a -> (a -> a) -> IO ()
This would have a lot of uses. I am aware of the "Implicit
Configurations" paper by Kiselyov and Shan, but a solution such as
theirs which requires modifying the type signatures of all
intermediate function calls is not suitable. I want to be able to say
"run algorithm A using database D" without requiring all of the
functions in algorithm A to know that databases are somehow involved.
One way to look at it is that I am seeking something like the
type-based approach, but easier and with less explicit syntax; another
way to look at it is that I am seeking something like a global IORef
based approach, but more safe.
An implementation based on ThreadId-keyed maps is almost workable:
data TLRef a = TLR a (MVar (Map ThreadId a))
The problem with this is that while it is possible to find out the
ThreadId of the current thread, it doesn't appear to be possible to
get the ThreadId of the parent thread, which would be needed for
values to be properly inherited.
Is there a way around this? Will there ever be standard support for
either finding the thread id of the parent of the current thread, or
for something like the thread-local references I have proposed?
Thanks,
Frederik