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
IO
monad too. First off, that manyunsafePerformIO
s is just bad.unsafePerformIO
should not be used in normal code.Right now, you're creating an action to write to the
IORef
which is of typeIO ()
, wrapping it up in theRight
constructor, and then throwing it away, you never actually use it.You can't
unsafePerformIO
it either since you're not strict in the value of theEither
value you constructed. This is whyunsafePerformIO
is bad, it's incredibly hard to reason about when/if things are going to happen.Instead try
And use the
EitherT
monad transform to stickIO
in there.