The GHC API requires that some initialisation occurs before invocation. Specifically, parseStaticFlags can only be called once.
I have functions that can call runGhc :: MaybeFilePath :: Ghc a -> IO a multiple times to run some GHC API methods. However, some of that initialisation should only occur the first time that function is called.
I seem to remember from Yi source that it is possible to create a global variable something like
ghcInitialised :: MVar (Bool,[String])
ghcInitialised = unsafePerformIO $ newMVar (False,[])
so that in the monadic action that calls runGhc we can have
(init,flags) <- readMVar ghcInitialised
when (not init) $ do
...
(_,_,staticFlagWarnings) <- parseStaticFlags ...
...
putMVar ghcInitialised (True,staticFlagWarnings)
However, I can not recall exactly how it is done. This code is in the runMonad function for the monad that wraps a GhcMonad. I am well aware that using unsafePerformIO is not pure or functional, but (at the time) this was the best way of achieving a practical result.
[Edit: the working solution:
{-# NOINLINE ghcInitialised #-}
ghcInitialised :: MVar (Bool,[String])
ghcInitialised = unsafePerformIO $ newMVar (False,[])
so that in the monadic action that calls runGhc we can have
(init,flags) <- takeMVar ghcInitialised
when (not init) $ do
...
(_,_,staticFlagWarnings) <- parseStaticFlags ...
...
putMVar ghcInitialised (True,staticFlagWarnings)
See this answer. It shows how to use a global counter that 'ticks' everytime you look at it. You don't need a counter, but instead of +1, you just put True into it.
Or, even better, you put the initialisation code into the unsafePerformIO, (guarded by an if of course).
You need to turn inlining off. The other important thing: The type has to be monomorph (= no type variables), otherwise you might evaluate unsafePerformIO for each actual type.
{-# NOINLINE ghcInitialised #-}
ghcInitialised :: MVar (Bool,[String])
ghcInitialised = unsafePerformIO $ newMVar (False,[])
来源:https://stackoverflow.com/questions/6488703/global-variables-via-unsafeperformio-in-haskell