
On Thu, Apr 27, 2006 at 11:09:58AM +0100, Adrian Hey wrote:
What really frustrates me about all this is that AFAIK there are no significant technical or theoretical reasons why we can't get this safety (without resort to the unsafePerformIO hack). The only serious obstacle seems political, with this very strange but apparently widespread dogma about so called "global variables" being inherently evil, regardless of the circumstances or purpose for which they are used.
indeed. perhaps we just need to come up with a more functional name than 'global variables'. like 'universal monad' or 'world transformer', maybe 'augmented IO'. :) I am tired of having to apologize for using them, they really are the right solution to a number of practical problems when writing real-world code. Every haskell programer depends on them whethre they know it or not, they are just abstracted away in libraries, but the bottom line is that someone needs to be able to write those libraries. my ForeignData proposal (on the wiki) fills a hole in the haskell FFI that can somewhat mitigate the problem, but only for Storable strict values. I have thought a safe 'StorableRef' would be a useful data type, that uses peeks and pokes internally for very fast mutable state, but provides a safe interface. There is also the 'dependingOn' primitive which is in jhc and I think will be in ghc (?) that lets you do global variables without having to turn off cse. dependingOn :: a -> b -> a dependingOn = ... where it has the same meaning as const, but introduces an artificial dependence of its return value on its second argument. so you can do data Var1 = Var1 {-# NOINLINE myVar #-} myVar :: IORef Int myVar = unsafePerformIO $ newIORef (0 `dependingOn` Var1) and now myVar cannot be cse'd with anything else because Var1 will not match anything of another type. still not ideal though. (I have been finding all sorts of uses for 'dependingOn' when it comes to various tasks)
Let me just add one thing. Sometimes you hear the argument "I need a global IORef here because it's to track the use of my single screen" (or keyboard, or elevator, or some some other gizmo in th real world).
heh. the canonical strawman tactic. :)
No, this is not the justification for the creation of top level TWI's. This is the justification for not requiring that the API that mutates a particular top level TWI state takes that state as an explicit argument. There's no point if there is (and can be) only one of them. This is why you don't have to pass an OS state handle to every IO function that interacts with "the" OS (note singular).
it is not just about convinience, for instance my 'Atom' module in jhc and ginsu depends on the fact you cannot pass in different states for correctness. its API is purly funcitonal, but it needs to use global state internally. Haskell has great tools for abstraction, global state would be another one. What it boils down to is that it helps you write more correct code in certain cases and there is no reasonable work-around. John -- John Meacham - ⑆repetae.net⑆john⑈