为什么我无法将值写入 IORef 但可以读取它



在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_。

相关内容

  • 没有找到相关文章

最新更新