    -- | An abstract interface to a unique symbol generator.
    module Data.Unique.Really (
        Unique, newUnique, hashUnique,
        ) where

    import Control.Applicative ((<$>))
    import Data.Hashable

    #if UseGHC

    import Control.Exception (evaluate)
    import qualified Data.Unique
    import System.Mem.StableName

    -- | An abstract unique value.
    -- Values of type 'Unique' may be compared for equality
    -- and hashed into Int.
    --
    -- Note: Unlike the symbols from "Data.Unique", the symbols from this
    -- module do not become equal after reloads in the GHC interpreter!
    newtype Unique = Unique (StableName Data.Unique.Unique) deriving (Unique -> Unique -> Bool
    (Unique -> Unique -> Bool)
    -> (Unique -> Unique -> Bool) -> Eq Unique
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Unique -> Unique -> Bool
    $c/= :: Unique -> Unique -> Bool
    == :: Unique -> Unique -> Bool
    $c== :: Unique -> Unique -> Bool
    Eq)

    newUnique :: IO Unique
    newUnique = do
        Unique
    x <- IO Unique
    Data.Unique.newUnique
        Unique
    _ <- Unique -> IO Unique
    forall a. a -> IO a
    evaluate Unique
    x
        StableName Unique -> Unique
    Unique (StableName Unique -> Unique)
    -> IO (StableName Unique) -> IO Unique
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Unique -> IO (StableName Unique)
    forall a. a -> IO (StableName a)
    makeStableName Unique
    x

    hashUnique :: Unique -> Int
    hashUnique (Unique s :: StableName Unique
    s) = StableName Unique -> Int
    forall a. StableName a -> Int
    hashStableName StableName Unique
    s

    #else

    import Data.IORef
    import System.IO.Unsafe (unsafePerformIO)

    {-# NOINLINE refNumber #-}
    refNumber :: IORef Integer
    refNumber = unsafePerformIO $ newIORef 0

    newNumber = atomicModifyIORef' refNumber $ \x -> let x' = x+1 in (x', x')

    -- | An abstract unique value.
    -- Values of type 'Unique' may be compared for equality
    -- and hashed into Int.
    --
    -- NOTE: You haven't compiled this module with GHC.
    -- The functionality will be identitcal to "Data.Unique".
    newtype Unique = Unique Integer deriving (Eq,Ord)

    newUnique = Unique <$> newNumber
    hashUnique (Unique s) = fromIntegral s

    #endif

    -- | Creates a new object of type 'Unique'.
    -- The value returned will not compare equal to any other
    -- value of type 'Unique' returned by previous calls to 'newUnique'.
    -- There is no limit on the number of times you may call this function.
    newUnique  :: IO Unique

    -- | Hashes a 'Unique' into an 'Int'.
    -- Two Uniques may hash to the same value, although in practice this is unlikely.
    -- The 'Int' returned makes a good hash key.
    hashUnique :: Unique -> Int

    instance Hashable Unique where hashWithSalt :: Int -> Unique -> Int
    hashWithSalt s :: Int
    s = Int -> Int -> Int
    forall a. Hashable a => Int -> a -> Int
    hashWithSalt Int
    s (Int -> Int) -> (Unique -> Int) -> Unique -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Unique -> Int
    hashUnique