Update Unique implementation to use BigInt.

This commit is contained in:
Nick Saunders 2023-03-06 17:58:36 -07:00
parent febb07ba50
commit a06a9117a0
7 changed files with 69 additions and 41 deletions

View File

@ -1,6 +1,7 @@
MIT License
Copyright (c) 2015-2017 mechairoi
Copyright (c) The University of Glasgow (Documentation)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -18,7 +18,8 @@
],
"dependencies": {
"purescript-prelude": "^6.0.0",
"purescript-effect": "^4.0.0"
"purescript-effect": "^4.0.0",
"purescript-refs": "^6.0.0"
},
"devDependencies": {
"purescript-console": "^6.0.0",

View File

@ -16,6 +16,7 @@
"description": "Data.Unique for PureScript",
"dependencies": {
"prelude": ">=6.0.0 <7.0.0",
"effect": ">=4.0.0 <5.0.0"
"effect": ">=4.0.0 <5.0.0",
"refs": ">=6.0.0 <7.0.0"
}
}

View File

@ -1,5 +1,5 @@
{ name = "unique"
, dependencies = [ "effect", "prelude" ]
, dependencies = [ "effect", "prelude", "refs" ]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs" ]
}

View File

@ -1,27 +1,29 @@
/* global exports */
"use strict";
export var zero = BigInt("0");
// module Data.Unique
var one = BigInt("1");
var MAX_SAFE_INTEGER = 9007199254740991;
var uniqueSource = [];
function iter(i) {
if (uniqueSource.length === i) {
for (var j = 0; j < i; ++j) uniqueSource[j] = 0;
uniqueSource[i] = 1;
} else {
if (uniqueSource[i] === MAX_SAFE_INTEGER) {
uniqueSource[i] = 0;
iter(i + 1);
} else {
uniqueSource[i]++;
}
}
export function eqImpl(a) {
return function(b) {
return a === b;
};
}
export function newUnique() {
iter(0);
return uniqueSource.length === 1 ? uniqueSource[0] + "" : uniqueSource.join(",");
};
export function ordImpl(lt) {
return function (eq) {
return function (gt) {
return function (x) {
return function (y) {
return x < y ? lt : x === y ? eq : gt;
};
};
};
};
}
export function addOne(x) {
return x + one;
}
export function hashUnique(x) {
return parseInt(BigInt.asIntN(32, x));
}

View File

@ -1,20 +1,41 @@
module Data.Unique
( newUnique
, Unique
) where
module Data.Unique (Unique, hashUnique, newUnique) where
import Prelude hiding (zero)
import Effect (Effect)
import Prelude (class Ord, class Eq, class Show, compare, (==))
import Effect.Ref (Ref)
import Effect.Ref as Ref
import Effect.Unsafe (unsafePerformEffect)
newtype Unique = Unique String
-- | An abstract unique object. Objects of type `Unique` may be compared for
-- | equality and ordering and hashed into `Int`.
foreign import data Unique :: Type
foreign import newUnique :: Effect Unique
foreign import eqImpl :: Unique -> Unique -> Boolean
instance showUnique :: Show Unique where
show (Unique a) = a
instance Eq Unique where
eq = eqImpl
instance eqUnique :: Eq Unique where
eq (Unique a) (Unique b) = a == b
foreign import ordImpl :: Ordering -> Ordering -> Ordering -> Unique -> Unique -> Ordering
instance ordUnique :: Ord Unique where
compare (Unique a) (Unique b) = compare a b
instance Ord Unique where
compare = ordImpl LT EQ GT
foreign import addOne :: Unique -> Unique
foreign import zero :: Unique
-- | Hashes a `Unique` into an `Int`. Two `Unique`s may hash to the same value,
-- | although in practice this is unlikely. The `Int` returned makes a good hash
-- | key.
foreign import hashUnique :: Unique -> Int
uniqSource :: Ref Unique
uniqSource = unsafePerformEffect (Ref.new zero)
-- | 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 `newUnique` may be
-- | called.
newUnique :: Effect Unique
newUnique = Ref.modify addOne uniqSource

View File

@ -1,7 +1,7 @@
module Test.Main where
import Prelude ((==), ($), (/=), discard, bind, Unit)
import Data.Unique (newUnique)
import Prelude
import Data.Unique (hashUnique, newUnique)
import Test.Assert (assert)
import Effect (Effect)
import Effect.Console (log)
@ -11,5 +11,7 @@ main = do
log "Test Data.Unique"
a <- newUnique
b <- newUnique
assert $ a /= b
assert $ a == a
assert $ a < b
assert $ hashUnique a == hashUnique a
assert $ hashUnique a /= hashUnique b