[Haskell] Re: Global Variables and IO initializers

Keean Schupke k.schupke at imperial.ac.uk
Fri Nov 5 16:07:27 EST 2004


Okay, now for the purposes of my understanding, let me explore this:

myRef :: IORef Int
myRef = unsafePerformIO $ newIORef 0

This should always return the same reference, whereas:

myIORef :: IO (IORef Int)
myIORef = newIORef 0

Will return a new reference every time. I agree it would seem that the first
form does not need to be in the IO monad as it is effectively a 
constant. The problem
I guess is there is no way in the language itself to indicate that the 
function should
not be inlined (which will make each use of myRef refer to a different 
IORef). So what
we need is a way in the type system to tell the compiler the function 
must have
a single unique definition... Something like:

myRef :: Unique (IORef Int)
myRef = uniquePerformIO $ newIORef 0

and then have:

runUnique :: Unique x -> x

Then modify the compilers to never inline fundtions in the Unique monad. 
Is this
what the CIO Monad proposes?

    Keean

Jules Bean wrote:

>
> On 5 Nov 2004, at 19:03, MR K P SCHUPKE wrote:
>
>>> You don't want stdin/stdout/stderr?
>>
>>
>> Also these are only available in the IO monad...
>>
>>> without breaking referential transparency
>>> by use of unsafePerformIO hack.
>>
>>
>> I don't understand this still... how can it not break referntial 
>> transparancy.
>> For example consider if stdin were available outside the IO monad.
>>
>> Could someone give an example of what these things are that need to 
>> be initialised
>> and that are safe.
>>
>
> The typical example is an IORef.
>
> As in:
>
> myRef :: IORef Int
> myRef = unsafePerformIO $ newIORef 0
>
> Now it's perfectly safe for myRef to exist outside the IO monad: all 
> it is, is some kind of pointer to the actual value. Of course, we 
> can't do anything to it outside the IO monad, but it can exist.
>
> Therefore, if it is at the toplevel, it can be referenced by all the 
> other functions in the same module. The functions therefore share a 
> common 'pointer' to a value: however none of them can actually access 
> the value or change it without using the IO monad, as is right and 
> proper.
>
> This is typical of the kind of commutative operations that Koen 
> proposes: what it is really about is 'fresh names'.  newIORef returns 
> a 'fresh name' for a 'box' which stores things.  (I notice that name 
> supply is one of the key issues for John Petersen too).
>
> There appears to be no problem in principle with having such objects 
> around at the top level, but haskell provides no syntax to create them 
> (safely). The syntax above is obviously 'wrong' in that it is rather 
> assuming that two different calls to unsafePerformIO $ newIORef 0 will 
> return different values, which violates ref. integrity.
>
> The compiler has something like an internal fresh name monad: every 
> time you define a new top-level value, it is given some fresh 
> (internal) name. Most language compilers can be thought of as 
> operating like this, but haskell makes it hard to get at the bit of 
> this monad we want.
>
> Jules
>



More information about the Haskell mailing list