
At 12:27 11/11/04 +0000, Ben Rudiak-Gould wrote:
Graham Klyne wrote:
Wouldn't it be easier to simply define "once" as a common Haskell library function?
Depends on the type and the expected semantics. As Adrian Hey already pointed out, (once :: IO a -> IO a) with the obvious semantics is never going to be safe, because it's just not the case that
x = once (newIORef ()) y = x
has the same intended meaning as
x = once (newIORef ()) y = once (newIORef ())
No amount of compiler-specific magic is going to fix this.
Ah, yes, I take the point now. Isn't this generally the case for any value in the IO monad? (Brushing a murky area of equivalence; the same IO computation used twice may yield different results, so I'm not clear to what extent it is meaningful to say that any IO value is the same as any other, including itself, in any observable sense.) #g --
On the other hand, these are perfectly safe:
once' :: IO a -> IO (IO a) oncePerString :: String -> IO a -> IO a oncePerType :: Typeable a => IO a -> IO a
once' seems virtually useless unless you have top-level <-, but the other two don't need it. I'm not sure which would be preferable. I lean toward oncePerString as more flexible and predictable, though it requires a certain discipline on the part of its users.
In any case there would need to be support for different scopes:
perProcess :: String -> IO a -> IO a perThread :: String -> IO a -> IO a perMachine :: String -> IO a -> IO a
I suppose you could add
perType :: Typeable a => IO a -> IO a
with the stipulation that types in different processes are distinct (which seems like the only safe assumption).
-- Ben
------------ Graham Klyne For email: http://www.ninebynine.org/#Contact