
| > I could be a bit out of date but I think Hugs uses different implementations | > because IO has concurrency and exceptions and ST doesn't. Apart from effort | > required, I don't know if there is any cost in switching. | | I think IORef and STRef have both been MUTVAR as far back as I can see. | The IO and (strict) ST monads used to be very different, and no longer | are (so they both use the same state primitives now), but I don't think | this affects the IORef = STRef IOState question. I'm a bit confused here. Is the proposal that the library design exposes to the programmer the following type synonyms: type IO a = ST IORegion a type IORef a = STRef IORegion a I think it is sound to do so. The advantage would be that newIORef and newSTRef would be the same (newRef, perhaps); ditto readRef, writeRef etc. I think this would be fine for GHC. It might not be fine for Hugs because they implement IO and ST differently I think. No idea about NHC. Or, alternatively, is the question something to do with the internals of the library, of interest to implementers but not to users of the library? Or is it just to do with the type of stToIO, which should be stToIO :: ST IORegion a -> IO a Simon

On Thu, Sep 18, 2003 at 08:56:40AM +0100, Simon Peyton-Jones wrote:
Is the proposal that the library design exposes to the programmer the following type synonyms:
type IO a = ST IORegion a type IORef a = STRef IORegion a
The proposal is to expose type IORef = STRef IORegion type IOArray = STArray IORegion type IOUArray = STUArray IORegion (modulo the name of IORegion) but to keep IO opaque. I think that while IO includes state, it is not itself a state monad (because the "state" there can be changed by other agents at the same time).
I think it is sound to do so. The advantage would be that newIORef and newSTRef would be the same (newRef, perhaps); ditto readRef, writeRef etc.
If IO is opaque, then we have newIORef = stToIO . newSTRef etc. It's not quite as generic as your version, but it is a conceptual simplification, and it does allow generic classes like class MonadST s m | m -> s where liftST :: Control.Monad.ST.ST s a -> m a with instances for IO, both ST's and various constructed monads, so we could have the likes of readSTRef' :: MonadST s m => STRef s a -> m a readSTRef' r = liftST (Data.STRef.readSTRef r) My problem with exposing the GHC implementation of IO is that I don't think it's the Truth, and Haskell has a record of punishing untruths sooner or later.
I think this would be fine for GHC. It might not be fine for Hugs because they implement IO and ST differently I think. No idea about NHC.
NHC doesn't have ST (rank-2 types). In Hugs, they are now newtype IO a = IO ((a -> IOResult) -> IOResult) newtype ST s a = ST (forall r. (a -> r) -> r) primitive newIORef "newRef" :: a -> IO (IORef a) primitive newSTRef "newRef" :: a -> ST s (STRef s a) But I'm not proposing that this be exposed.
Or, alternatively, is the question something to do with the internals of the library, of interest to implementers but not to users of the library? Or is it just to do with the type of stToIO, which should be
stToIO :: ST IORegion a -> IO a
It's more a matter of making IORegion work a bit harder since we have to put it in the interface anyway.

In article <20030918091948.GA29877@soi.city.ac.uk>,
Ross Paterson
NHC doesn't have ST (rank-2 types). In Hugs, they are now
newtype IO a = IO ((a -> IOResult) -> IOResult) newtype ST s a = ST (forall r. (a -> r) -> r)
Oh now that's interesting. Presumably in Hugs IO and ST s could be made instances of MonadCont very easily? How does Hugs do fixIO? -- Ashley Yakeley, Seattle WA

On Thu, Sep 18, 2003 at 04:01:08PM -0700, Ashley Yakeley wrote:
In article <20030918091948.GA29877@soi.city.ac.uk>, Ross Paterson
wrote: NHC doesn't have ST (rank-2 types). In Hugs, they are now
newtype IO a = IO ((a -> IOResult) -> IOResult) newtype ST s a = ST (forall r. (a -> r) -> r)
Oh now that's interesting. Presumably in Hugs IO and ST s could be made instances of MonadCont very easily?
I view it a trick to force sequencing (like GHC's state transformer representation of IO, and similarly inaccurate), not to be exposed in the interface (including special instances). (But it does make stToIO and runST easy to implement.)
How does Hugs do fixIO?
It's nothing deep: fixIO :: (a -> IO a) -> IO a fixIO f = do r <- newIORef (throw NonTermination) x <- f (unsafePerformIO (readIORef r)) writeIORef r x return x I'm not claiming this is valid for all continuation monads, or other representations of IO. I don't even think IO is really a continuation monad (or a state transformer).

In article <20030919000856.GA1240@soi.city.ac.uk>,
Ross Paterson
How does Hugs do fixIO?
It's nothing deep:
Oh, you've just moved the cleverness to unsafePerformIO, presumably: newtype IO a = IO ((a -> IOResult) -> IOResult) unsafePerformIO :: IO a -> a unsafePerformIO (IO f) = unsafeCast (f unsafeCast) -- Ashley Yakeley, Seattle WA

On Fri, Sep 19, 2003 at 02:36:55AM -0700, Ashley Yakeley wrote:
In article <20030919000856.GA1240@soi.city.ac.uk>, Ross Paterson
wrote: How does Hugs do fixIO?
It's nothing deep:
Oh, you've just moved the cleverness to unsafePerformIO, presumably:
newtype IO a = IO ((a -> IOResult) -> IOResult) unsafePerformIO :: IO a -> a unsafePerformIO (IO f) = unsafeCast (f unsafeCast)
"cleverness" isn't the word I'd have used, but there's more to it than this (because Hugs supports cooperative concurrency). See Hugs.{Prelude,IO,IOExts,Conc} under hugs98/libraries on cvs.haskell.org for the gory details.
participants (3)
-
Ashley Yakeley
-
Ross Paterson
-
Simon Peyton-Jones