Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate Unique Values Each Time A Function Is Called?

Tags:

haskell

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.

like image 236
George Avatar asked Dec 13 '22 12:12

George


2 Answers

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.)

like image 147
Daniel Wagner Avatar answered Jan 04 '23 22:01

Daniel Wagner


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.

like image 32
Jon Purdy Avatar answered Jan 05 '23 00:01

Jon Purdy