全局变量通过Haskell中的unsafePerformIO [英] Global variables via unsafePerformIO in Haskell

查看:217
本文介绍了全局变量通过Haskell中的unsafePerformIO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆