module Data.Ref where

import System.Mem.StableName
import System.IO.Unsafe
import Control.Applicative

--------------------------------------------------------------------------------
-- * References
--------------------------------------------------------------------------------

data Ref a = Ref { Ref a -> StableName a
label :: StableName a, Ref a -> a
deref :: a }

instance Eq (Ref a) where
  Ref StableName a
s1 a
_ == :: Ref a -> Ref a -> Bool
== Ref StableName a
s2 a
_ = StableName a
s1 StableName a -> StableName a -> Bool
forall a. Eq a => a -> a -> Bool
== StableName a
s2

instance Show a => Show (Ref a) where
  show :: Ref a -> String
show (Ref StableName a
s a
x) = String
"(Ref " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (StableName a -> Int
forall a. StableName a -> Int
hashStableName StableName a
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

ref :: a -> Ref a
ref :: a -> Ref a
ref a
x = IO (Ref a) -> Ref a
forall a. IO a -> a
unsafePerformIO (IO (Ref a) -> Ref a) -> IO (Ref a) -> Ref a
forall a b. (a -> b) -> a -> b
$ (StableName a -> a -> Ref a) -> a -> StableName a -> Ref a
forall a b c. (a -> b -> c) -> b -> a -> c
flip StableName a -> a -> Ref a
forall a. StableName a -> a -> Ref a
Ref a
x (StableName a -> Ref a) -> IO (StableName a) -> IO (Ref a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> IO (StableName a)
forall a. a -> IO (StableName a)
makeStableName a
x
{-# NOINLINE ref #-}

--------------------------------------------------------------------------------
-- the end.