Generating an unique ID from two values

What would be an idiomatic way of generating an unique number (say, a 64bit unsigned int) from two values, in such a way that the input values (also numbers of the same type) could be regenerated from the number, as a Haskell function?

On C/C++ I would probably use something like

result = (((value1) << BITS) + ((value2) & ((1 << BITS) - 1)))

and, accordingly,

value1 = (result >> BITS)

and

value2 = (result & ((1 << BITS) - 1))

for regenerating the values, but I don't think I should be trying to use bitwise operations in Haskell.

After consideration, I simply abandoned the idea of using bitwise operations and resorted to Cantor's pairing function:

pair :: (Fractional a) => a -> a -> a
pair x y = (1 / 2) * (x + y) * (x + y + 1) + y

unpair :: (RealFrac a, Floating a) => a -> (a, a)
unpair z = (x, y) where
    q = (-1 / 2) + sqrt (1 / 4 + 2 * z)
    j = fromInteger (truncate q)
    y = z - ((1 / 2) * j * (j + 1))
    x = j - y

This is probably the way I should have thought from the beginning. Thank you all very much for helping me to better understand bit operations on Haskell, though.


You can use the exact same way in Haskell. Bitwise operations can be found in Data.Bits and unsigned, fixed-sized integer types in Data.Word . For example:

import Data.Bits
import Data.Word

combine :: Word32 -> Word32 -> Word64
combine a b = (fromIntegral a `shiftL` 32) + fromIntegral b

separate :: Word64 -> (Word32, Word32)
separate w = (fromIntegral $ w `shiftR` 32, fromIntegral $ w .&. 0xffff)

The thing that might trip you up compared to C is that Haskell never converts between different numeric types implicitly, so you need to use fromIntegral to convert between eg 32bit and 64bit unsigned integers.

链接地址: http://www.djcxy.com/p/6366.html

上一篇: 寻找可重放/有些无状态的PRNG算法

下一篇: 从两个值生成唯一的ID