How do I make a Haskell function which generates a unique value every time it's called over the course of a program?
One idea is:
incrementInteger :: IO (Integer)
incrementInteger = -- ...
such that it increments each time it is called over the course of the program (no matter which thread it's called from, etc).
incrementIngeter
=> 0
incrementInteger
=> 1
incrementInteger
=> 2
That said, the only property I care about for this function "no matter what, the value is unique each time it is called". How to do this?
EDIT: It looks like Data.UUID provides this via generatedNamed
.
The base
package offers newUnique
for this purpose. (N.B. these values will be unique within a single program run, but not necessarily across runs.)
I would probably solve this using State Integer
at first—or if the code is already in IO
, then by writing a wrapper for ReaderT (IORef Integer) IO
. It’s easier to understand code that makes it explicit which functions can access and modify the value, compared to a global counter.
However, if all else fails and you really do want it to be program-global, the usual unsafe way to do it in GHC Haskell is:
import Data.IORef
import System.IO.Unsafe (unsafePerformIO)
-- A global mutable counter
-- The NOINLINE is critical to ensure the counter is unique
counter :: IORef Integer
counter = unsafePerformIO (newIORef 0)
{-# NOINLINE counter #-}
-- Atomically increment the counter and return its current value
next :: IO Integer
next = atomicModifyIORef' counter (\ x -> (x + 1, x))
Data.Unique
in base
uses this implementation under the hood, but does not provide access to the underlying integer. There are also various packages on Hackage providing similar unique ID generation—GUIDs, UUIDs, &c.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With