我如何制作一个Haskell函数,该函数每次在程序过程中被调用时都会生成一个唯一值?
一个想法是:
incrementInteger :: IO (Integer)
incrementInteger = -- ...
使得它每次在程序过程中被调用时都递增(无论从哪个线程调用,等等)。
incrementIngeter
=> 0
incrementInteger
=> 1
incrementInteger
=> 2
也就是说,我对此函数唯一关心的属性是“无论如何,每次调用该值都是唯一的”。该怎么做?
编辑:看来Data.UUID是通过generatedNamed
提供的。
答案 0 :(得分:7)
base
软件包为此提供了newUnique
。 (注:这些值在单个程序运行中将是唯一的,但不一定跨运行。)
答案 1 :(得分:5)
我可能首先会使用State Integer
来解决此问题,或者如果代码已经在IO
中,然后为ReaderT (IORef Integer) IO
编写包装,则可能会解决。与全局计数器相比,更易于理解的代码可以明确指出哪些函数可以访问和修改值。
但是,如果所有其他方法都失败了,并且您确实希望它是程序全局的,那么在GHC Haskell中通常使用的不安全方法是:
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
中的 base
在幕后使用此实现,但不提供对基础整数的访问。在Hackage上也有各种软件包提供类似的唯一ID生成-GUID,UUID和&c。