
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.
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. 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.
So please, no more handwaving arguments about this kind of thing being unnecessary, bad programming style, or whatever...
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, it seems it would be better to find an alternative. If you could give more details of the application someone may be able to suggest a resonable way of refactoring. Keean.