I believe you are safe to do this for now with GHC.  There is some relevant discussion here [1].

[1]: http://www.haskell.org/haskellwiki/Top_level_mutable_state

Note that doing:

    {-# NOINLINE counter #-}
    counter :: TVar Int
    counter = unsafePerformIO $ atomically $ newTVar 0

Is not safe [2].

[2]: http://hackage.haskell.org/package/stm-2.4.2/docs/Control-Concurrent-STM-TVar.html#v:newTVarIO

Ryan




On Wed, Jan 29, 2014 at 2:32 AM, Alexander Alexeev <mail@eax.me> wrote:
Hello!

Lets consider the following code:

import Control.Concurrent
import Control.Concurrent.STM
import System.IO.Unsafe (unsafePerformIO)

{-# NOINLINE counter #-}
counter :: TVar Int
counter = unsafePerformIO $ newTVarIO 0

incCounter :: IO Int
incCounter = do
  r <- atomically $ do
    t <- readTVar counter
    let t' = t + 1
    writeTVar counter t'
    return t'
  return r

main :: IO ()
main = do
  n1 <- incCounter
  print n1
  n2 <- incCounter
  print n2
  n3 <- incCounter
  print n3

This program prints:

1
2
3

So we have a "global variable". Do I right understand that newTVarIO
creates TVar and RTS memoizes it since 'counter' function is pure? If
it's true, could it happen that under some circumstances memoized value
will be deleted from memory? Or Haskell keeps all memoized values
forever?

Another issue which I'm afraid of --- would the given code be safe in
multithread application? For example, is it possible to encounter a
race condition if two threads will try to create a new counter in the
same time?

Is there any other problems which should be taken in account?

--
Best regards,
Alexander Alexeev
http://eax.me/
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe