lhc-0.6.20081210.1: lib/base/src/Lhc/ACIO.hs
{-# OPTIONS_LHC -N #-}
module Lhc.ACIO where
import Lhc.IORef
import Lhc.IO
import Lhc.Monad
newtype ACIO a = ACIO (IO a)
deriving(Monad,Functor)
unsafeIOToACIO :: IO a -> ACIO a
unsafeIOToACIO x = ACIO x
acioToIO :: ACIO a -> IO a
acioToIO (ACIO x) = x
newIORefAC :: a -> ACIO (IORef a)
newIORefAC a = unsafeIOToACIO (newIORef a)
runOnce :: IO a -> ACIO (IO a)
runOnce action = do
ref <- newIORefAC Nothing
return $ do
v <- readIORef ref
case v of
Just v -> return v
Nothing -> do
v <- action
writeIORef ref v
return v
{-@Extensions
# Top Level Actions
Lhc supports monadic actions declared at the top level of your module. These
can be used to do things such as initialize IORefs or allocate static data. An example
of a top level action is the following.
import Lhc.ACIO
import Data.IORef
ref <- newIORefAC 0
count = do
modifyIORef ref (1 +)
readIORef ref >>= print
main = do
count
count
count
Which will print 1, 2, and 3. A special monad ACIO (which stands for Affine
Central IO) is provided to restrict what may take place in top level actions.
Basically, top level actions can only consist of IO that can be omitted or
reordered without changing the meaning of a program. In practice, this means
that it does not matter whether such actions are all performed at the beginning
or are only computed once on demand.
If you need to use arbitrary IO, a utility function 'runOnce' is provided.
using it you can ensure arbitrary IO actions are run only once and the return
values shared, however you must access the value inside the IO monad, thus
ensuring program integrity. An example using a hypothetical GUI library is below.
import Lhc.ACIO
getWindow <- runOnce $ do
connection <- newGUIConnection
window <- createWindow (640,480)
setTitle window "My Global Window"
return window
main = do
w <- getWindow
draw w "Hello!"
Note, top level global variables can be indicative of design issues. In
general, they should only be used when necessary to interface with an external
library, opaque uses inside a library where the shared state can not be
externally observed, or inside your Main program as design dictates.
-}