在haskell中,我需要一个全局变量,所以我选择使用IORef插槽,这是我的计划:
memo :: IORef Int
memo = unsafePerformIO $ newRefInt 9999
evaluate ARGs s = do
v <- Right $ unsafePerformIO $ readIORef memo
val <- Right $ VInt v
return $ (val, s)
evaluate (Call funcID exp) s = do
...
Right $ writeIORef memo 100
...
我的计划是,当执行器评估"Call"节点时,它会将参数保存到插槽中。然后,当评估"ARGs"节点时,将读取该备忘录槽。
但无论我做什么,我只能读取9999,但不能将新值写入该插槽。
甚至我也试过:
memo :: IORef Int
memo = unsafePerformIO $ newRefInt 9999
evaluate ARGs s = do
Right $ writeIORef memo 100
v <- Right $ unsafePerformIO $ readIORef memo
val <- Right $ VInt v
return $ (val, s)
结果仍然是备忘录=9999。为什么?
因为写入也在IO
monad中。首先,这么多unsafePerformIO
太糟糕了。unsafePerformIO
不应在正常代码中使用。
现在,您正在创建一个操作来写入类型为IO ()
的IORef
,将其封装在Right
构造函数中,然后将其丢弃,您从未实际使用过它。
您也不能unsafePerformIO
,因为您对构建的Either
值的值并不严格。这就是为什么unsafePerformIO
很糟糕的原因,很难推断事情何时/是否会发生。
请尝试
evaluate ARGs s = do
liftIO $ writeIORef memo 100
v <- liftIO $ readIORef memo
val <- return $ VInt v
return $ (val, s)
并用CCD_ 10 monad变换把CCD_。