Please, no tirade about banishing unsafePerformIO. I've seen this done before I just don't remember how. I want to use a state monad to count things, but don't want to monadify the thing I'm using the counter in. basically, i want a function getVar :: () -> String which returns a new string every time. i tried this:
curVarId = newSTRef (0 :: Integer)
{-# NO-INLINE newVar -}
newVar = \_ -> ('\0' : show x) where y = unsafePerformIO (stToIO curVarId) x = unsafePerformIO $ stToIO $ do x <- readSTRef y writeSTRef y (x + 1) return x
and in ghci it works wonderfully, but when i actually compile, all i get is "\NUL0". what's the proper way to write this? thanks - hal
basically, i want a function getVar :: () -> String which returns a new string every time. i tried this:
curVarId = newSTRef (0 :: Integer)
{-# NO-INLINE newVar -}
newVar = \_ -> ('\0' : show x) where y = unsafePerformIO (stToIO curVarId) x = unsafePerformIO $ stToIO $ do x <- readSTRef y writeSTRef y (x + 1) return x
and in ghci it works wonderfully, but when i actually compile, all i get is "\NUL0".
what's the proper way to write this?
I think (haven't tested this one) you should write (modulo layout): | curVarIdRef :: IORef Integer | curVarIdRef = unsafePerformIO $ newIORef (0 :: Integer) | | {-# NO-INLINE newVar -} | | newVar :: () -> String | newVar = \_ -> ('\0' : show x) where | x = unsafePerformIO $ | do x <- readIORef curVarIdRef | writeIORef curVarIdRef (x + 1) | return x Because in your original version, curVarId allocates a new reference to 0 every time newVar is called. Hope this works, Jan de Wit
participants (2)
-
Hal Daume III -
Jan de Wit