3

GHC API では、呼び出しの前に何らかの初期化が行われる必要があります。具体的には、parseStaticFlags一度だけ呼び出すことができます。

runGhc :: MaybeFilePath :: Ghc a -> IO aいくつかの GHC API メソッドを実行するために複数回呼び出すことができる関数があります。ただし、その初期化の一部は、その関数が最初に呼び出されたときにのみ発生する必要があります。

Yi次のようなグローバル変数を作成できることをソースから覚えているようです

ghcInitialised :: MVar (Bool,[String])
ghcInitialised = unsafePerformIO $ newMVar (False,[])

そのため、呼び出すモナド アクションでrunGhc使用できます。

(init,flags) <- readMVar ghcInitialised
when (not init) $ do
   ...
   (_,_,staticFlagWarnings) <- parseStaticFlags ...
   ...
   putMVar ghcInitialised (True,staticFlagWarnings)

しかし、それがどのように行われたかを正確に思い出すことはできません。このコードは、runMonada をラップするモナドの関数にありGhcMonadます。using が純粋でも機能的でもないことは十分承知していunsafePerformIOますが、(当時は) これが実用的な結果を達成するための最良の方法でした。

[編集: 実用的なソリューション:

{-# NOINLINE ghcInitialised #-}
ghcInitialised :: MVar (Bool,[String])
ghcInitialised = unsafePerformIO $ newMVar (False,[])

そのため、呼び出すモナド アクションでrunGhc使用できます。

(init,flags) <- takeMVar ghcInitialised
when (not init) $ do
   ...
   (_,_,staticFlagWarnings) <- parseStaticFlags ...
   ...
   putMVar ghcInitialised (True,staticFlagWarnings)
4

2 に答える 2

2

インライン化をオフにする必要があります。もう 1 つの重要なこと: 型はモノモーフ (= 型変数なし) でなければなりません。そうしないと、実際の型ごとに unsafePerformIO を評価する可能性があります。

{-# NOINLINE ghcInitialised #-}
ghcInitialised :: MVar (Bool,[String])
ghcInitialised = unsafePerformIO $ newMVar (False,[])
于 2011-06-28T13:48:00.480 に答える
1

この回答を参照してください。見るたびに「刻む」グローバル カウンターの使用方法を示します。カウンターは必要ありませんが、 の代わりに+1入れるだけTrueです。

または、さらに良いことに、初期化コードを , に入れますunsafePerformIO(もちろん、保護されていifます)。

于 2011-06-27T08:40:54.187 に答える