Reputation: 8277
I've noticed this idiom in Data.Unique:
uniqSource :: TVar Integer
uniqSource = unsafePerformIO (newTVarIO 0)
{-# NOINLINE uniqSource #-}
Is it guaranteed to only run once?
Upvotes: 11
Views: 496
Reputation: 40797
In GHC, yes.1 See the documentation for more information; there is a variant unsafeDupablePerformIO
that can be executed multiple times that avoids the overhead dedicated to achieving this guarantee.
Note that unsafePerformIO
to create mutable variables isn't safe in general; as described in the documentation, you can create a polymorphic reference and use it to implement unsafeCoerce
. That's not something you're likely to do accidentally, though, and it doesn't apply to the code in question (since the type of the reference is specified explicitly).
The safe-globals package abstracts this "idiom" (while useful in some cases, it's generally considered an antipattern, and should not be used in normal code) in a way that ensures safety.
See also my previous answer on unsafePerformIO
and the caution that must be used when applying it.
1 I'm pretty sure it applies to all other implementations, too; the special care GHC takes to avoid repeated execution is only necessary in a threaded setting, and I don't know of any other threaded implementations of Haskell. GHC is the only implementation people really use these days, though...
Upvotes: 11