[Haskell] Re: Global Variables and IO initializers

Adrian Hey ahey at iee.org
Sun Nov 7 23:56:05 EST 2004


Please, can we confine this discussion to just one mailing list:-)

It started out on haskell at haskell.org so that's where I'd like
to keep it (at least that's where I will be posting my responses
from now on).

On Sunday 07 Nov 2004 10:38 pm, Keean Schupke wrote:
> >I don't understand the relevance of this. In the example I gave
> >we're not talking about an abstract data structure and the init
> >function is not stateless.
>
> Well, it works like this, to call any function in your library
> you must present a state-type. The only way to get a
> state-type would be to call the init function. Therefore the
> type system enforces that initialisation has occured
> before a function is called. The user would not need to
> call the initialiser again as you would pass the state-type
> between functions. The neatest way to do this would be
> to make functions in your interface instances of a
> state-monad-transformer that could be layered over the
> IO monad.

So how does this _prevent_ the user calling realInit twice?

Also, you seem to be assuming that the parameter returned by
realInit is a some kind of state reference that must be passed
as an argument to every function that is dependent on that state.
There may be something to be said for that approach (for the reasons
you give), but it's also rather tiresome to do this.
(Almost as awkward as Cleans unique environment passing.)

But maybe realInit simply returns a Bool to indicate whether or
not initialisation is successful (as is typical with C). Or maybe
it just returns () if there's no possibility of failure.

I certainly could design the realInit binding so that it returns
an abstract state reference, and I could insist that every function
in the library takes that state reference as an argument. But why
should I make life so awkward for both myself and library users,
especially as AFAICS it does not stop realInit being used twice
or more.

> >I can assure you that for the intended applications of oneShot it
> >is vital that realInit is executed once at most, but the user must
> >have the freedom to execute userInit as many times as they need
> >(I.E. without the burden of having to keep track of whether or not
> >they've used it before).
>
> I don't understand this - If you pass the state type you
> do not need to call init again.

Please just take my word for it that that realInit can never
be used more than once. That is the basic premise of this problem.
The user may not need to use it more than once, but that doesn't mean
they won't, and in fact it may be rather awkward for them to ensure
they don't (other than by using oneShot or similar mechanism themselves
at the top level).

> It would work like openFile,
> which seems easy enough for users to understand is
> called only once on a file to get the filehandle that is used
> with the IO functions. You can call the state-type returned
> from your library an opaque-handle, and treat it like a file
> handle.

No it wouldn't. realInit is not an "act of creation" which
may be used again and again to create more and more things.
It is an act of initialisation of a unique external resource.

> I am only trying to understand the need for this. As it
> appears the cost of using the unsafePerformIO style is that
> certain optimisations need to be switched off.

They only need to be switched off for an entire module because of
the use of unsafePerformIO. This is the problem, not the use of
top level <- bindings (if they existed).

So why not fix the language to make the use of unsafePerformIO
unnecessary?

> it seems it would be better to find an alternative.

Sure there are alternatives, darned awkward ones AFAICS.

Why should this awkwardness be forced upon us because of (what appears
to me) a dogmatic belief that top level "things with identity" are a bad 
thing?

Why are they a bad thing?

Why are top level IORefs any worse than other IORefs (for
example)?

[I hope nobody is going to bring up the old type security chestnut
in response to this question. We've already been over that ground.]

> If you could give
> more details of the application someone may be able to
> suggest a resonable way of refactoring.

The problem is to ensure that a top level IO action cannot be
executed more than once. 

Regards
--
Adrian Hey



More information about the Haskell mailing list