全局变量通过Haskell中的unsafePerformIO [英] Global variables via unsafePerformIO in Haskell
问题描述
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)
然而,我不记得它是如何完成的。此代码位于包装 GhcMonad
的monad的 runMonad
函数中。我清楚地知道,使用 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)
请参阅此答案。它展示了如何使用一个全局计数器,每次你看它时都会'勾号'。你不需要一个计数器,而是 +1
,你只需要把 True
加入它。
或者,更好的办法是将初始化代码放入 unsafePerformIO
中,(由 if
当然)。
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).
这篇关于全局变量通过Haskell中的unsafePerformIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!