[Haskell-cafe] One-shot? (was: Global variables and stuff)

Ben Rudiak-Gould Benjamin.Rudiak-Gould at cl.cam.ac.uk
Thu Nov 11 07:27:17 EST 2004

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.

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

More information about the Haskell-Cafe mailing list