Module Initialisation? (was Re: [Haskell] (no subject))

Wolfgang Thaller wolfgang.thaller at
Sat Oct 16 23:45:44 EDT 2004

Adrian Hey wrote:

> I'm puzzled about this idea of "module init action" in a declarative
> language. Perhaps, if it's desirable to have some module initialisation
> applied to a module if anything from it is used, the way to do this 
> would
> be to have a reserved identifier specially for the purpose, like
> "main", but at the module level. (Though this idea still seems a
> bit strange to me).

I don't see what's so strange about that. At least, it's not any 
stranger than on-demand execution of IO actions in a pure functional 
language. And the toplevel "<-" is definitely a natural syntax for 

> I've interpreted this correctly this means that someAction will always
> get executed, whether or not foo (or anything dependent on foo) is used
> elsewhere? This seems like a bad thing to me.

It's a feature. I'd actually _want_ to use that one independently.

> It may be harmless enough
> if all it does is create a few IORefs which are then promptly garbage
> collected, but in some situations it could involve quite complex
> and expensive initialisation operations on foreign libraries
> (for example).

Well if you want those IO operations to be lazily interleaved with the 
rest of the program (or not executed at all), you can use

valueToBeInitedLazily <- unsafeInterleaveIO $ do

... which explicitly says what you are doing that might be slightly 

> Since a lot of the concerns expressed about this seem to centre
> around possible abuse of arbitrary IO operations in these top
> level constructions, maybe the problem could be addressed by
> insisting that a restricted monad was used, call it SafeIO say.

You're taking away a feature I want to use.
1) Initialising global IORefs is a good thing, no matter when it's 
actually done.
2) Being able to initialize things at program startup is a good thing, 
even if they're
not explicitly referred to.
3) Lazy, on-demand initialization of things is a good thing, if you 
know what you're doing.
4) Lazy, on-demand initialization of things (with potential side 
effects) is a bad thing, if you don't know what you're doing.

If we define toplevel IO bindings to be just like the unsafePerformIO 
hack, we get 1,3 and 4 (and 4 is actually a bad thing).
If we define toplevel IO bindings as mdo-style module initialisation, 
we get 1 and 2 directly, and 3 with an obvious use of 
unsafeInterleaveIO. We don't get 4, because obviously, when you use 
unsafeInterleaveIO, you're already claiming to know what you're doing.

Also note that if useless initialization of IORefs ever becomes a 
problem, we can still use lots of nasty hacks inside the compiler to 
optimize for those common functions. But I don't think we'll ever have 
to do this.



More information about the Haskell mailing list