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
_______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell