[Haskell] thread-local variables

Frederik Eaton frederik at a5.repetae.net
Sat Aug 5 14:56:38 EDT 2006

> > > As said before the monadic approach can be quite clean. I haven't used
> > > implicit parameters that much, so I won't comment on them.
> > 
> > Perhaps you can give an example? As I said, a single monad won't
> > suffice for me, because different libraries only know about different
> > parts of the state. With TLS, one can delimit the scope of parameters
> > by making the references to them module-internal, for instance.
> > 
> > With monads, I imagine that I'll need for each parameter
> > 
> > (1) a MonadX class, with a liftX member
> > (2) a catchX function
> > (3) a MonadY instance, for each wrapped monad Y (thus the number of
> > such instances will be O(n^2) where n is the number of parameters)
> That is usually the wrong approach. Newtype something like
> "StateT AppState IO". Use something like:
> runWithPart :: (AppState -> c) -> (c -> IO a) -> AppM a
> to define nice actions for different parts of the libraries.
> Usually this is very easy if one uses combinators and high level
> constructs and messier if it is hard to find the right combinators.
> If you look at the various web frameworks in Haskell you will notice
> that most of them live happily with one monad and don't suffer from
> problems because of that.

That doesn't answer the question: What if my application has a need
for several different sets of parameters - what if it doesn't make
sense to combine them into a single monad? What if there are 'n'
layers? Is it incorrect to say that the monadic approach requires code
size O(n^2)?

> > With TLS, I need
> > 
> > (1) a declaration "x = unsafePerformIO $ newIOParam ..."
> And don't have any static guarantees that you have done all the proper
> initialization calls before you use them.

Well, there are a lot of things I don't have static guarantees for. 
For instance, sometimes I call the function 'head', and the compiler
isn't able to verify that the argument isn't an empty list. If I
initialize my TLS to 'undefined' then I'll get a similar error
message, at run time. For another example, I don't use monadic regions
when I do file IO. I can live with that.

> ... Also if we have two pieces of the same per-thread state that we
> wish to use in one thread (e.g. db-connections) then the TLS
> approach becomes quite hard.

No harder than the monadic approach, in my opinion.

> Here is a naive and dirty implementation. The largest problem is that
> TypeRep is not in  Ord. An alternative approach using Dynamic would be
> possible, but I like the connection between the key 
> and the associated type.
> http://www.cs.helsinki.fi/u/ekarttun/haskell/TLS/
> Not optimized for performance at all.

You've redefined 'fork'. If I want a library which works with other
libraries, that will not be an option. The original purpose of my
posting to this thread was to ask for two standard functions which
would let me define thread-local variables in a way which is
interoperable with other libraries, to the same extent as 'withArgs'
and 'withProgName' are.



More information about the Haskell mailing list