packages feed

vault-0.3.2.0: src/Data/Vault/ST/backends/GHC.h

-- This implementation is specific to GHC because it uses Any,
-- from and to which it is valid to unsafeCoerce any type.  Using
-- unsafeCoerce avoids picking up a Typeable constraint. This
-- implementation is more efficient than the alternative implementation
-- in terms of IORef.

import Data.Unique.Really.GHC
import GHC.Exts (Any)
import Unsafe.Coerce (unsafeCoerce)

import qualified Data.HashMap.LAZINESS as Map
type Map = Map.HashMap

toAny :: a -> Any
toAny = unsafeCoerce

fromAny :: Any -> a
fromAny = unsafeCoerce

{-----------------------------------------------------------------------------
    Vault
------------------------------------------------------------------------------}
newtype Vault s = Vault (Map Unique Any)
newtype Key s a = Key Unique

#if __GLASGOW_HASKELL__ >= 708
type role Vault nominal
type role Key nominal representational
#endif

newKey = unsafeIOToST $ Key <$> newUnique

lookup (Key k) (Vault m) = fromAny <$> Map.lookup k m

insert (Key k) x (Vault m) = Vault $ Map.insert k (toAny x) m

adjust f (Key k) (Vault m) = Vault $ Map.adjust f' k m
    where f' = toAny . f . fromAny

delete (Key k) (Vault m) = Vault $ Map.delete k m

{-----------------------------------------------------------------------------
    Locker
------------------------------------------------------------------------------}
data Locker s = Locker !Unique !Any

lock (Key k) = Locker k . toAny

unlock (Key k) (Locker k' a)
  | k == k' = Just $ fromAny a
  | otherwise = Nothing