
| -----Original Message----- | From: Ross Paterson [mailto:ross@soi.city.ac.uk] | Sent: 18 September 2003 10:20 | To: Simon Peyton-Jones | Cc: Alastair Reid; Simon Marlow; libraries@haskell.org | Subject: Re: RealWorld | | 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). Aha. I hadn't realised that you want to expose IORef as an STRef, but not the IO monad itself. I certainly don't object to that, but I'm not sure of all the implications. For example, at the moment one could have class MRef m r | m -> r, r -> m where new :: a -> m (r a) read :: r a -> m a write :: r a -> a -> m () instance MRef IO IORef where ... instance MRef (ST s) (STRef s) where ... I don't think that'll be legal if IORef = STRef IORegion, because the "r->m" dependency becomes ambiguous. So we'd have to lose the "r->m" dependency. Maybe that's ok. (I don't think MRef currently exists in the libraries.) But it's an example of a consequence of the choice you suggest. Simon | | > 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.