[Haskell] Re: Global Variables and IO initializers

Krasimir Angelov ka2_mail at yahoo.com
Mon Nov 8 05:19:33 EST 2004

--- Ben Rudiak-Gould
<Benjamin.Rudiak-Gould at cl.cam.ac.uk> wrote:
> This is solved by merging the IO and ST monads,
> something that ought to 
> be done anyway:
>     type IO = ST RealWorld
>     type IORef a = Ref RealWorld a
>     type STRef s a = Ref s a
>     newRef :: a -> ST s (Ref s a)   -- replaces
> newIORef and newSTRef
>     readRef :: Ref s a -> ST s a
>     writeRef :: Ref s a -> a -> ST s ()
>     ...
> A top-level init action would look like
>     r <- newRef 'x'
> The RHS has type (forall s. ST s (Ref s Char)). The
> runtime system runs 
> it through (id :: forall a. (forall s. ST s a) -> ST
> RealWorld a), with 
> a resulting type of ST RealWorld (Ref RealWorld
> Char), which is the same 
> as IO (IORef Char). So r ends up with the type IORef
> Char.

The type of the expression:

id (newRef 'x')

isn't (ST RealWorld (Ref RealWorld Char)). GHC gives
an error:

Inferred type is less polymorphic than expected
    Quantified type variable `s' escapes
In the first argument of `cast', namely `(newSTRef

I like this proposal. It merges not only IORef with
STRef but also IOArray with STArray. In the base
package there are also Data.HashTable and Data.Unique.
Currently they can be used only from IO monad but it
is perfectly safe to use them from ST if we change the
interface a litle bit.

data Hashtable s key val = ..
data Unique s = ..

The proposal gives us more generalizations and don't
introduce any new monads. In order to get proper
typing we must move the state parameter to the end:

data Ref val s = ..
data Hashtable key val s = ..
data Unique s = ..

In the above example the expression was:

r <- newRef 'x'

We need an additional function:

runSTInit :: (forall s . ST s (a s)) -> a RealWorld

In this case the compiler must translate the above to:

r = runSTInit (newRef 'x')

where the type of r is:

r :: Ref Char RealWorld    {- == IORef Char -}

Note that 2-rank type of runSTInit doesn't allow to
execute regular IO actions. Even that (ST s a) allows
actions like readRef and writeRef. This allows to
initialise local references but doesn't allow to
access other toplevel reverences since they are bound
to RealWorld state.


Do you Yahoo!? 
Check out the new Yahoo! Front Page. 

More information about the Haskell mailing list