In haskell, I need a global variable so I choose to use IORef slot, here is my plan:
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
...
My plan is when the executer evaluates the "Call" node, it will save the parameter into the slot. Then when the "ARGs" node are evaluated, that memo slot would be read.
But whatever I do, I just can read 9999 but cannot write a new value into that slot.
Even I tried:
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)
It will still result that memo = 9999. Why?
Because writing is in the
IOmonad too. First off, that manyunsafePerformIOs is just bad.unsafePerformIOshould not be used in normal code.Right now, you're creating an action to write to the
IORefwhich is of typeIO (), wrapping it up in theRightconstructor, and then throwing it away, you never actually use it.You can't
unsafePerformIOit either since you're not strict in the value of theEithervalue you constructed. This is whyunsafePerformIOis bad, it's incredibly hard to reason about when/if things are going to happen.Instead try
And use the
EitherTmonad transform to stickIOin there.