git.iko.soy/rowtype-yoga/purescript-unique
on master help sign in
Merge pull request #4 from nsaunders/bigint

Update `Unique` implementation to use `BigInt`.

commit602cd3d5364027a87f0093bf9f216124eb2257ed authorNick Saunders <nick@saunde.rs> dateTue 7 Mar 2023, 04:55 (4 years ago) parent347e007a06a911
7 files changed+68−40
LICENSE+1 bower.json+2−1 purs.json+2−1 spago.dhall+1−1 src/Data/Unique.js+23−21 src/Data/Unique.purs+34−13 test/Main.purs+5−3
LICENSE+1
@@ -1,6 +1,7 @@
11MIT License
22
33Copyright (c) 2015-2017 mechairoi
4+Copyright (c) The University of Glasgow (Documentation)
45
56Permission is hereby granted, free of charge, to any person obtaining a copy
67of this software and associated documentation files (the "Software"), to deal
bower.json+2−1
@@ -18,7 +18,8 @@
1818 ],
1919 "dependencies": {
2020 "purescript-prelude": "^6.0.0",
21− "purescript-effect": "^4.0.0"
21+ "purescript-effect": "^4.0.0",
22+ "purescript-refs": "^6.0.0"
2223 },
2324 "devDependencies": {
2425 "purescript-console": "^6.0.0",
purs.json+2−1
@@ -16,6 +16,7 @@
1616 "description": "Data.Unique for PureScript",
1717 "dependencies": {
1818 "prelude": ">=6.0.0 <7.0.0",
19− "effect": ">=4.0.0 <5.0.0"
19+ "effect": ">=4.0.0 <5.0.0",
20+ "refs": ">=6.0.0 <7.0.0"
2021 }
2122}
spago.dhall+1−1
@@ -1,5 +1,5 @@
11{ name = "unique"
2−, dependencies = [ "effect", "prelude" ]
2+, dependencies = [ "effect", "prelude", "refs" ]
33, packages = ./packages.dhall
44, sources = [ "src/**/*.purs" ]
55}
src/Data/Unique.js+23−21
@@ -1,27 +1,29 @@
1−/* global exports */
2−"use strict";
1+export var zero = BigInt("0");
32
4−// module Data.Unique
3+var one = BigInt("1");
54
6−var MAX_SAFE_INTEGER = 9007199254740991;
7−var uniqueSource = [];
5+export function eqImpl(a) {
6+ return function(b) {
7+ return a === b;
8+ };
9+}
810
9−function iter(i) {
10− if (uniqueSource.length === i) {
11− for (var j = 0; j < i; ++j) uniqueSource[j] = 0;
12− uniqueSource[i] = 1;
13− } else {
14− if (uniqueSource[i] === MAX_SAFE_INTEGER) {
15− uniqueSource[i] = 0;
16− iter(i + 1);
17− } else {
18− uniqueSource[i]++;
19− }
20− }
11+export function ordImpl(lt) {
12+ return function (eq) {
13+ return function (gt) {
14+ return function (x) {
15+ return function (y) {
16+ return x < y ? lt : x === y ? eq : gt;
17+ };
18+ };
19+ };
20+ };
2121}
2222
23−export function newUnique() {
24− iter(0);
25− return uniqueSource.length === 1 ? uniqueSource[0] + "" : uniqueSource.join(",");
26−};
23+export function addOne(x) {
24+ return x + one;
25+}
2726
27+export function hashUnique(x) {
28+ return parseInt(BigInt.asIntN(32, x));
29+}
src/Data/Unique.purs+34−13
@@ -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
test/Main.purs+5−3
@@ -1,7 +1,7 @@
11module Test.Main where
22
3−import Prelude ((==), ($), (/=), discard, bind, Unit)
4−import Data.Unique (newUnique)
3+import Prelude
4+import Data.Unique (hashUnique, newUnique)
55import Test.Assert (assert)
66import Effect (Effect)
77import Effect.Console (log)
@@ -11,5 +11,7 @@ main = do
1111 log "Test Data.Unique"
1212 a <- newUnique
1313 b <- newUnique
14− assert $ a /= b
1514 assert $ a == a
15+ assert $ a < b
16+ assert $ hashUnique a == hashUnique a
17+ assert $ hashUnique a /= hashUnique b