diff --git a/LICENSE b/LICENSE index bb308cc..30a891b 100644 --- a/LICENSE +++ b/LICENSE @@ -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 diff --git a/bower.json b/bower.json index 94e3c4b..d11a160 100644 --- a/bower.json +++ b/bower.json @@ -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", diff --git a/purs.json b/purs.json index 5a56abf..38bf7b9 100644 --- a/purs.json +++ b/purs.json @@ -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" } } diff --git a/spago.dhall b/spago.dhall index 5c9df4c..4dff66e 100644 --- a/spago.dhall +++ b/spago.dhall @@ -1,5 +1,5 @@ { name = "unique" -, dependencies = [ "effect", "prelude" ] +, dependencies = [ "effect", "prelude", "refs" ] , packages = ./packages.dhall , sources = [ "src/**/*.purs" ] } diff --git a/src/Data/Unique.js b/src/Data/Unique.js index c541d5d..0f2ae6a 100644 --- a/src/Data/Unique.js +++ b/src/Data/Unique.js @@ -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)); +} \ No newline at end of file diff --git a/src/Data/Unique.purs b/src/Data/Unique.purs index 21dc7d8..a84706b 100644 --- a/src/Data/Unique.purs +++ b/src/Data/Unique.purs @@ -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 \ No newline at end of file diff --git a/test/Main.purs b/test/Main.purs index 9d28159..cdc62ec 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -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 \ No newline at end of file