@@ -1,20 +1,41 @@
1−module Data.Unique
2− ( newUnique
3− , Unique
4− ) where
1+module Data.Unique (Unique, hashUnique, newUnique) where
2+
3+import Prelude hiding (zero)
54
65import Effect (Effect)
7−import Prelude (class Ord, class Eq, class Show, compare, (==))
6+import Effect.Ref (Ref)
7+import Effect.Ref as Ref
8+import Effect.Unsafe (unsafePerformEffect)
9+
10+-- | An abstract unique object. Objects of type `Unique` may be compared for
11+-- | equality and ordering and hashed into `Int`.
12+foreign import data Unique :: Type
13+
14+foreign import eqImpl :: Unique -> Unique -> Boolean
15+
16+instance Eq Unique where
17+ eq = eqImpl
18+
19+foreign import ordImpl :: Ordering -> Ordering -> Ordering -> Unique -> Unique -> Ordering
20+
21+instance Ord Unique where
22+ compare = ordImpl LT EQ GT
823
9−newtype Unique = Unique String
24+foreign import addOne :: Unique -> Unique
1025
11−foreign import newUnique :: Effect Unique
26+foreign import zero :: Unique
1227
13−instance showUnique :: Show Unique where
14− show (Unique a) = a
28+-- | Hashes a `Unique` into an `Int`. Two `Unique`s may hash to the same value,
29+-- | although in practice this is unlikely. The `Int` returned makes a good hash
30+-- | key.
31+foreign import hashUnique :: Unique -> Int
1532
16−instance eqUnique :: Eq Unique where
17− eq (Unique a) (Unique b) = a == b
33+uniqSource :: Ref Unique
34+uniqSource = unsafePerformEffect (Ref.new zero)
1835
19−instance ordUnique :: Ord Unique where
20− compare (Unique a) (Unique b) = compare a b
36+-- | Creates a new object of type `Unique`. The value returned will not compare
37+-- | equal to any other value of type `Unique` returned by previous calls to
38+-- | `newUnique`. There is no limit on the number of times `newUnique` may be
39+-- | called.
40+newUnique :: Effect Unique
41+newUnique = Ref.modify addOne uniqSource