diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e306283b..00000000 --- a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/.* -!/.gitignore -!/.jscsrc -!/.jshintrc -!/.travis.yml -/bower_components/ -/node_modules/ -/output/ diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 342da669..00000000 --- a/.jscsrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "preset": "grunt", - "disallowSpacesInAnonymousFunctionExpression": null, - "requireSpacesInAnonymousFunctionExpression": { - "beforeOpeningRoundBrace": true, - "beforeOpeningCurlyBrace": true - }, - "disallowSpacesInsideObjectBrackets": null, - "requireSpacesInsideObjectBrackets": "all", - "validateQuoteMarks": "\"", - "requireCurlyBraces": null -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 2240be2a..00000000 --- a/.jshintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "bitwise": true, - "eqeqeq": true, - "forin": true, - "freeze": true, - "funcscope": true, - "futurehostile": true, - "strict": "global", - "latedef": true, - "maxparams": 1, - "noarg": true, - "nocomma": true, - "nonew": true, - "notypeof": true, - "singleGroups": true, - "undef": true, - "unused": true, - "eqnull": true -} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 791313a3..00000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: node_js -sudo: false -node_js: - - 0.10 -env: - - PATH=$HOME/purescript:$PATH -install: - - TAG=$(wget -q -O - https://github.com/purescript/purescript/releases/latest --server-response --max-redirect 0 2>&1 | sed -n -e 's/.*Location:.*tag\///p') - - wget -O $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz - - tar -xvf $HOME/purescript.tar.gz -C $HOME/ - - chmod a+x $HOME/purescript - - npm install -script: - - npm run build diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 94158580..00000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 PureScript - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 8fdd5cdc..68b23cff 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,5 @@ -# purescript-maps +# DEPRECATED -[![Latest release](http://img.shields.io/bower/v/purescript-maps.svg)](https://github.com/purescript/purescript-maps/releases) -[![Build Status](https://travis-ci.org/purescript/purescript-maps.svg?branch=master)](https://travis-ci.org/purescript/purescript-maps) -[![Dependency Status](https://www.versioneye.com/user/projects/55848c1b363861001d000315/badge.svg?style=flat)](https://www.versioneye.com/user/projects/55848c1b363861001d000315) +The library is no longer maintained under this repository, it has been merged into to [`purescript-ordered-collections`](https://github.com/purescript/purescript-ordered-collections). -Purely-functional map data structures. - -## Installation - -``` -bower install purescript-maps -``` - -## Module documentation - -- [Data.Map](docs/Data/Map.md) -- [Data.StrMap](docs/Data/StrMap.md) -- [Data.StrMap.ST](docs/Data/StrMap/ST.md) -- [Data.StrMap.ST.Unsafe](docs/Data/StrMap/ST/Unsafe.md) -- [Data.StrMap.Unsafe](docs/Data/StrMap/Unsafe.md) +[The previous releases](https://github.com/purescript-deprecated/purescript-maps/releases) will continue to work for older libraries that still depend on them. diff --git a/bower.json b/bower.json deleted file mode 100644 index c030c253..00000000 --- a/bower.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "purescript-maps", - "homepage": "https://github.com/purescript/purescript-maps", - "authors": [ - "Phil Freeman ", - "John A. De Goes " - ], - "description": "Purely functional maps implemented in PureScript", - "keywords": [ - "purescript" - ], - "repository": { - "type": "git", - "url": "git://github.com/purescript/purescript-maps.git" - }, - "license": "MIT", - "ignore": [ - "**/.*", - "bower_components", - "node_modules", - "output", - "test", - "bower.json", - "package.json" - ], - "dependencies": { - "purescript-lists": "^0.7.0", - "purescript-st": "^0.1.0", - "purescript-functions": "^0.1.0" - }, - "devDependencies": { - "purescript-quickcheck": "^0.12.0" - } -} diff --git a/docs/Data/Map.md b/docs/Data/Map.md deleted file mode 100644 index 1c32d000..00000000 --- a/docs/Data/Map.md +++ /dev/null @@ -1,209 +0,0 @@ -## Module Data.Map - -This module defines a type of maps as balanced 2-3 trees, based on - - -#### `Map` - -``` purescript -data Map k v -``` - -`Map k v` represents maps from keys of type `k` to values of type `v`. - -##### Instances -``` purescript -(Eq k, Eq v) => Eq (Map k v) -(Show k, Show v) => Show (Map k v) -(Ord k, Ord v) => Ord (Map k v) -(Ord k) => Semigroup (Map k v) -(Ord k) => Monoid (Map k v) -Functor (Map k) -Foldable (Map k) -(Ord k) => Traversable (Map k) -``` - -#### `showTree` - -``` purescript -showTree :: forall k v. (Show k, Show v) => Map k v -> String -``` - -Render a `Map` as a `String` - -#### `empty` - -``` purescript -empty :: forall k v. Map k v -``` - -An empty map - -#### `isEmpty` - -``` purescript -isEmpty :: forall k v. Map k v -> Boolean -``` - -Test if a map is empty - -#### `singleton` - -``` purescript -singleton :: forall k v. k -> v -> Map k v -``` - -Create a map with one key/value pair - -#### `checkValid` - -``` purescript -checkValid :: forall k v. Map k v -> Boolean -``` - -Check whether the underlying tree satisfies the 2-3 invariant - -This function is provided for internal use. - -#### `lookup` - -``` purescript -lookup :: forall k v. (Ord k) => k -> Map k v -> Maybe v -``` - -Lookup a value for the specified key - -#### `member` - -``` purescript -member :: forall k v. (Ord k) => k -> Map k v -> Boolean -``` - -Test if a key is a member of a map - -#### `insert` - -``` purescript -insert :: forall k v. (Ord k) => k -> v -> Map k v -> Map k v -``` - -Insert a key/value pair into a map - -#### `delete` - -``` purescript -delete :: forall k v. (Ord k) => k -> Map k v -> Map k v -``` - -Delete a key and its corresponding value from a map - -#### `alter` - -``` purescript -alter :: forall k v. (Ord k) => (Maybe v -> Maybe v) -> k -> Map k v -> Map k v -``` - -Insert the value, delete a value, or update a value for a key in a map - -#### `update` - -``` purescript -update :: forall k v. (Ord k) => (v -> Maybe v) -> k -> Map k v -> Map k v -``` - -Update or delete the value for a key in a map - -#### `fromFoldable` - -``` purescript -fromFoldable :: forall f k v. (Ord k, Foldable f) => f (Tuple k v) -> Map k v -``` - -Convert any foldable collection of key/value pairs to a map. -On key collision, later values take precedence over earlier ones. - -#### `fromFoldableWith` - -``` purescript -fromFoldableWith :: forall f k v. (Ord k, Foldable f) => (v -> v -> v) -> f (Tuple k v) -> Map k v -``` - -Convert any foldable collection of key/value pairs to a map. -On key collision, the values are configurably combined. - -#### `toList` - -``` purescript -toList :: forall k v. Map k v -> List (Tuple k v) -``` - -Convert a map to a list of key/value pairs - -#### `fromList` - -``` purescript -fromList :: forall k v. (Ord k) => List (Tuple k v) -> Map k v -``` - -Create a map from a list of key/value pairs - -#### `fromListWith` - -``` purescript -fromListWith :: forall k v. (Ord k) => (v -> v -> v) -> List (Tuple k v) -> Map k v -``` - -Create a map from a list of key/value pairs, using the specified function -to combine values for duplicate keys. - -#### `keys` - -``` purescript -keys :: forall k v. Map k v -> List k -``` - -Get a list of the keys contained in a map - -#### `values` - -``` purescript -values :: forall k v. Map k v -> List v -``` - -Get a list of the values contained in a map - -#### `unionWith` - -``` purescript -unionWith :: forall k v. (Ord k) => (v -> v -> v) -> Map k v -> Map k v -> Map k v -``` - -Compute the union of two maps, using the specified function -to combine values for duplicate keys. - -#### `union` - -``` purescript -union :: forall k v. (Ord k) => Map k v -> Map k v -> Map k v -``` - -Compute the union of two maps, preferring values from the first map in the case -of duplicate keys - -#### `unions` - -``` purescript -unions :: forall k v f. (Ord k, Foldable f) => f (Map k v) -> Map k v -``` - -Compute the union of a collection of maps - -#### `size` - -``` purescript -size :: forall k v. Map k v -> Int -``` - -Calculate the number of key/value pairs in a map - - diff --git a/docs/Data/StrMap.md b/docs/Data/StrMap.md deleted file mode 100644 index ac92562c..00000000 --- a/docs/Data/StrMap.md +++ /dev/null @@ -1,263 +0,0 @@ -## Module Data.StrMap - -This module defines a type of native Javascript maps which -require the keys to be strings. - -To maximize performance, Javascript objects are not wrapped, -and some native code is used even when it's not necessary. - -#### `StrMap` - -``` purescript -data StrMap :: * -> * -``` - -`StrMap a` represents a map from `String`s to values of type `a`. - -##### Instances -``` purescript -Functor StrMap -Foldable StrMap -Traversable StrMap -(Eq a) => Eq (StrMap a) -(Show a) => Show (StrMap a) -(Semigroup a) => Semigroup (StrMap a) -(Semigroup a) => Monoid (StrMap a) -``` - -#### `thawST` - -``` purescript -thawST :: forall a h r. StrMap a -> Eff (st :: ST h | r) (STStrMap h a) -``` - -Convert an immutable map into a mutable map - -#### `freezeST` - -``` purescript -freezeST :: forall a h r. STStrMap h a -> Eff (st :: ST h | r) (StrMap a) -``` - -Convert a mutable map into an immutable map - -#### `runST` - -``` purescript -runST :: forall a r. (forall h. Eff (st :: ST h | r) (STStrMap h a)) -> Eff r (StrMap a) -``` - -Freeze a mutable map, creating an immutable map. Use this function as you would use -`Prelude.runST` to freeze a mutable reference. - -The rank-2 type prevents the map from escaping the scope of `runST`. - -#### `fold` - -``` purescript -fold :: forall a z. (z -> String -> a -> z) -> z -> StrMap a -> z -``` - -Fold the keys and values of a map - -#### `foldMap` - -``` purescript -foldMap :: forall a m. (Monoid m) => (String -> a -> m) -> StrMap a -> m -``` - -Fold the keys and values of a map, accumulating values using -some `Monoid`. - -#### `foldM` - -``` purescript -foldM :: forall a m z. (Monad m) => (z -> String -> a -> m z) -> z -> StrMap a -> m z -``` - -Fold the keys and values of a map, accumulating values and effects in -some `Monad`. - -#### `foldMaybe` - -``` purescript -foldMaybe :: forall a z. (z -> String -> a -> Maybe z) -> z -> StrMap a -> z -``` - -Fold the keys and values of a map. - -This function allows the folding function to terminate the fold early, -using `Maybe`. - -#### `all` - -``` purescript -all :: forall a. (String -> a -> Boolean) -> StrMap a -> Boolean -``` - -Test whether all key/value pairs in a `StrMap` satisfy a predicate. - -#### `empty` - -``` purescript -empty :: forall a. StrMap a -``` - -An empty map - -#### `isSubmap` - -``` purescript -isSubmap :: forall a. (Eq a) => StrMap a -> StrMap a -> Boolean -``` - -Test whether one map contains all of the keys and values contained in another map - -#### `isEmpty` - -``` purescript -isEmpty :: forall a. StrMap a -> Boolean -``` - -Test whether a map is empty - -#### `size` - -``` purescript -size :: forall a. StrMap a -> Number -``` - -Calculate the number of key/value pairs in a map - -#### `singleton` - -``` purescript -singleton :: forall a. String -> a -> StrMap a -``` - -Create a map with one key/value pair - -#### `lookup` - -``` purescript -lookup :: forall a. String -> StrMap a -> Maybe a -``` - -Lookup the value for a key in a map - -#### `member` - -``` purescript -member :: forall a. String -> StrMap a -> Boolean -``` - -Test whether a `String` appears as a key in a map - -#### `insert` - -``` purescript -insert :: forall a. String -> a -> StrMap a -> StrMap a -``` - -Insert a key and value into a map - -#### `delete` - -``` purescript -delete :: forall a. String -> StrMap a -> StrMap a -``` - -Delete a key and value from a map - -#### `alter` - -``` purescript -alter :: forall a. (Maybe a -> Maybe a) -> String -> StrMap a -> StrMap a -``` - -Insert, remove or update a value for a key in a map - -#### `update` - -``` purescript -update :: forall a. (a -> Maybe a) -> String -> StrMap a -> StrMap a -``` - -Remove or update a value for a key in a map - -#### `fromFoldable` - -``` purescript -fromFoldable :: forall f a. (Foldable f) => f (Tuple String a) -> StrMap a -``` - -Create a map from a foldable collection of key/value pairs - -#### `fromFoldableWith` - -``` purescript -fromFoldableWith :: forall f a. (Foldable f) => (a -> a -> a) -> f (Tuple String a) -> StrMap a -``` - -Create a map from a foldable collection of key/value pairs, using the -specified function to combine values for duplicate keys. - -#### `fromList` - -``` purescript -fromList :: forall a. List (Tuple String a) -> StrMap a -``` - -Create a map from a list of key/value pairs - -#### `fromListWith` - -``` purescript -fromListWith :: forall a. (a -> a -> a) -> List (Tuple String a) -> StrMap a -``` - -Create a map from a list of key/value pairs, using the specified function -to combine values for duplicate keys. - -#### `toList` - -``` purescript -toList :: forall a. StrMap a -> List (Tuple String a) -``` - -Convert a map into a list of key/value pairs - -#### `keys` - -``` purescript -keys :: forall a. StrMap a -> Array String -``` - -Get an array of the keys in a map - -#### `values` - -``` purescript -values :: forall a. StrMap a -> List a -``` - -Get a list of the values in a map - -#### `union` - -``` purescript -union :: forall a. StrMap a -> StrMap a -> StrMap a -``` - -Compute the union of two maps, preferring the first map in the case of -duplicate keys. - -#### `unions` - -``` purescript -unions :: forall a. List (StrMap a) -> StrMap a -``` - -Compute the union of a collection of maps - - diff --git a/docs/Data/StrMap/ST.md b/docs/Data/StrMap/ST.md deleted file mode 100644 index 135d883b..00000000 --- a/docs/Data/StrMap/ST.md +++ /dev/null @@ -1,51 +0,0 @@ -## Module Data.StrMap.ST - -Helper functions for working with mutable maps using the `ST` effect. - -This module can be used when performance is important and mutation is a local effect. - -#### `STStrMap` - -``` purescript -data STStrMap :: * -> * -> * -``` - -A reference to a mutable map - -The first type parameter represents the memory region which the map belongs to. The second type parameter defines the type of elements of the mutable array. - -The runtime representation of a value of type `STStrMap h a` is the same as that of `StrMap a`, except that mutation is allowed. - -#### `new` - -``` purescript -new :: forall a h r. Eff (st :: ST h | r) (STStrMap h a) -``` - -Create a new, empty mutable map - -#### `peek` - -``` purescript -peek :: forall a h r. STStrMap h a -> String -> Eff (st :: ST h | r) (Maybe a) -``` - -Get the value for a key in a mutable map - -#### `poke` - -``` purescript -poke :: forall a h r. STStrMap h a -> String -> a -> Eff (st :: ST h | r) (STStrMap h a) -``` - -Update the value for a key in a mutable map - -#### `delete` - -``` purescript -delete :: forall a h r. STStrMap h a -> String -> Eff (st :: ST h | r) (STStrMap h a) -``` - -Remove a key and the corresponding value from a mutable map - - diff --git a/docs/Data/StrMap/ST/Unsafe.md b/docs/Data/StrMap/ST/Unsafe.md deleted file mode 100644 index a94aa46d..00000000 --- a/docs/Data/StrMap/ST/Unsafe.md +++ /dev/null @@ -1,13 +0,0 @@ -## Module Data.StrMap.ST.Unsafe - -#### `unsafeGet` - -``` purescript -unsafeGet :: forall a h r. STStrMap h a -> Eff (st :: ST h | r) (StrMap a) -``` - -Unsafely get the map out of ST without copying it - -If you later change the ST version of the map the pure value will also change. - - diff --git a/docs/Data/StrMap/Unsafe.md b/docs/Data/StrMap/Unsafe.md deleted file mode 100644 index fa884986..00000000 --- a/docs/Data/StrMap/Unsafe.md +++ /dev/null @@ -1,13 +0,0 @@ -## Module Data.StrMap.Unsafe - -#### `unsafeIndex` - -``` purescript -unsafeIndex :: forall a. StrMap a -> String -> a -``` - -Unsafely get the value for a key in a map. - -This function does not check whether the key exists in the map. - - diff --git a/package.json b/package.json deleted file mode 100644 index fcbd3a85..00000000 --- a/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "private": true, - "scripts": { - "postinstall": "pulp dep install", - "build": "jshint src && jscs src && pulp test && rimraf docs && pulp docs" - }, - "devDependencies": { - "jscs": "^1.13.1", - "jshint": "^2.9.1-rc.1", - "pulp": "^4.0.2", - "rimraf": "^2.4.1" - } -} diff --git a/src/Data/Map.purs b/src/Data/Map.purs deleted file mode 100644 index c98be78d..00000000 --- a/src/Data/Map.purs +++ /dev/null @@ -1,301 +0,0 @@ --- | This module defines a type of maps as balanced 2-3 trees, based on --- | - -module Data.Map - ( Map() - , showTree - , empty - , isEmpty - , singleton - , checkValid - , insert - , lookup - , fromFoldable - , fromFoldableWith - , toList - , fromList - , fromListWith - , delete - , member - , alter - , update - , keys - , values - , union - , unionWith - , unions - , size - ) where - -import Prelude - -import Data.Foldable (foldl, foldMap, foldr, Foldable) -import Data.List (List(..), length, nub) -import Data.Maybe (Maybe(..), maybe, isJust) -import Data.Maybe.Unsafe (unsafeThrow) -import Data.Monoid (Monoid) -import Data.Traversable (traverse, Traversable) -import Data.Tuple (Tuple(..), uncurry) - --- | `Map k v` represents maps from keys of type `k` to values of type `v`. -data Map k v - = Leaf - | Two (Map k v) k v (Map k v) - | Three (Map k v) k v (Map k v) k v (Map k v) - -instance eqMap :: (Eq k, Eq v) => Eq (Map k v) where - eq m1 m2 = toList m1 == toList m2 - -instance showMap :: (Show k, Show v) => Show (Map k v) where - show m = "fromList " ++ show (toList m) - -instance ordMap :: (Ord k, Ord v) => Ord (Map k v) where - compare m1 m2 = compare (toList m1) (toList m2) - -instance semigroupMap :: (Ord k) => Semigroup (Map k v) where - append = union - -instance monoidMap :: (Ord k) => Monoid (Map k v) where - mempty = empty - -instance functorMap :: Functor (Map k) where - map _ Leaf = Leaf - map f (Two left k v right) = Two (map f left) k (f v) (map f right) - map f (Three left k1 v1 mid k2 v2 right) = Three (map f left) k1 (f v1) (map f mid) k2 (f v2) (map f right) - -instance foldableMap :: Foldable (Map k) where - foldl f z m = foldl f z (values m) - foldr f z m = foldr f z (values m) - foldMap f m = foldMap f (values m) - -instance traversableMap :: (Ord k) => Traversable (Map k) where - traverse f ms = foldr (\x acc -> union <$> x <*> acc) (pure empty) (((<$>) (uncurry singleton)) <$> (traverse f <$> toList ms)) - sequence = traverse id - --- | Render a `Map` as a `String` -showTree :: forall k v. (Show k, Show v) => Map k v -> String -showTree Leaf = "Leaf" -showTree (Two left k v right) = - "Two (" ++ showTree left ++ - ") (" ++ show k ++ - ") (" ++ show v ++ - ") (" ++ showTree right ++ ")" -showTree (Three left k1 v1 mid k2 v2 right) = - "Three (" ++ showTree left ++ - ") (" ++ show k1 ++ - ") (" ++ show v1 ++ - ") (" ++ showTree mid ++ - ") (" ++ show k2 ++ - ") (" ++ show v2 ++ - ") (" ++ showTree right ++ ")" - --- | An empty map -empty :: forall k v. Map k v -empty = Leaf - --- | Test if a map is empty -isEmpty :: forall k v. Map k v -> Boolean -isEmpty Leaf = true -isEmpty _ = false - --- | Create a map with one key/value pair -singleton :: forall k v. k -> v -> Map k v -singleton k v = Two Leaf k v Leaf - --- | Check whether the underlying tree satisfies the 2-3 invariant --- | --- | This function is provided for internal use. -checkValid :: forall k v. Map k v -> Boolean -checkValid tree = length (nub (allHeights tree)) == one - where - allHeights :: Map k v -> List Int - allHeights Leaf = pure zero - allHeights (Two left _ _ right) = map (\n -> n + one) (allHeights left ++ allHeights right) - allHeights (Three left _ _ mid _ _ right) = map (\n -> n + one) (allHeights left ++ allHeights mid ++ allHeights right) - --- | Lookup a value for the specified key -lookup :: forall k v. (Ord k) => k -> Map k v -> Maybe v -lookup _ Leaf = Nothing -lookup k (Two _ k1 v _) | k == k1 = Just v -lookup k (Two left k1 _ _) | k < k1 = lookup k left -lookup k (Two _ _ _ right) = lookup k right -lookup k (Three _ k1 v1 _ _ _ _) | k == k1 = Just v1 -lookup k (Three _ _ _ _ k2 v2 _) | k == k2 = Just v2 -lookup k (Three left k1 _ _ _ _ _) | k < k1 = lookup k left -lookup k (Three _ k1 _ mid k2 _ _) | k1 < k && k <= k2 = lookup k mid -lookup k (Three _ _ _ _ _ _ right) = lookup k right - --- | Test if a key is a member of a map -member :: forall k v. (Ord k) => k -> Map k v -> Boolean -member k m = isJust (k `lookup` m) - -data TreeContext k v - = TwoLeft k v (Map k v) - | TwoRight (Map k v) k v - | ThreeLeft k v (Map k v) k v (Map k v) - | ThreeMiddle (Map k v) k v k v (Map k v) - | ThreeRight (Map k v) k v (Map k v) k v - -fromZipper :: forall k v. (Ord k) => List (TreeContext k v) -> Map k v -> Map k v -fromZipper Nil tree = tree -fromZipper (Cons (TwoLeft k1 v1 right) ctx) left = fromZipper ctx (Two left k1 v1 right) -fromZipper (Cons (TwoRight left k1 v1) ctx) right = fromZipper ctx (Two left k1 v1 right) -fromZipper (Cons (ThreeLeft k1 v1 mid k2 v2 right) ctx) left = fromZipper ctx (Three left k1 v1 mid k2 v2 right) -fromZipper (Cons (ThreeMiddle left k1 v1 k2 v2 right) ctx) mid = fromZipper ctx (Three left k1 v1 mid k2 v2 right) -fromZipper (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) right = fromZipper ctx (Three left k1 v1 mid k2 v2 right) - -data KickUp k v = KickUp (Map k v) k v (Map k v) - --- | Insert a key/value pair into a map -insert :: forall k v. (Ord k) => k -> v -> Map k v -> Map k v -insert = down Nil - where - down :: List (TreeContext k v) -> k -> v -> Map k v -> Map k v - down ctx k v Leaf = up ctx (KickUp Leaf k v Leaf) - down ctx k v (Two left k1 _ right) | k == k1 = fromZipper ctx (Two left k v right) - down ctx k v (Two left k1 v1 right) | k < k1 = down (Cons (TwoLeft k1 v1 right) ctx) k v left - down ctx k v (Two left k1 v1 right) = down (Cons (TwoRight left k1 v1) ctx) k v right - down ctx k v (Three left k1 _ mid k2 v2 right) | k == k1 = fromZipper ctx (Three left k v mid k2 v2 right) - down ctx k v (Three left k1 v1 mid k2 _ right) | k == k2 = fromZipper ctx (Three left k1 v1 mid k v right) - down ctx k v (Three left k1 v1 mid k2 v2 right) | k < k1 = down (Cons (ThreeLeft k1 v1 mid k2 v2 right) ctx) k v left - down ctx k v (Three left k1 v1 mid k2 v2 right) | k1 < k && k <= k2 = down (Cons (ThreeMiddle left k1 v1 k2 v2 right) ctx) k v mid - down ctx k v (Three left k1 v1 mid k2 v2 right) = down (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) k v right - - up :: List (TreeContext k v) -> KickUp k v -> Map k v - up Nil (KickUp left k v right) = Two left k v right - up (Cons (TwoLeft k1 v1 right) ctx) (KickUp left k v mid) = fromZipper ctx (Three left k v mid k1 v1 right) - up (Cons (TwoRight left k1 v1) ctx) (KickUp mid k v right) = fromZipper ctx (Three left k1 v1 mid k v right) - up (Cons (ThreeLeft k1 v1 c k2 v2 d) ctx) (KickUp a k v b) = up ctx (KickUp (Two a k v b) k1 v1 (Two c k2 v2 d)) - up (Cons (ThreeMiddle a k1 v1 k2 v2 d) ctx) (KickUp b k v c) = up ctx (KickUp (Two a k1 v1 b) k v (Two c k2 v2 d)) - up (Cons (ThreeRight a k1 v1 b k2 v2) ctx) (KickUp c k v d) = up ctx (KickUp (Two a k1 v1 b) k2 v2 (Two c k v d)) - --- | Delete a key and its corresponding value from a map -delete :: forall k v. (Ord k) => k -> Map k v -> Map k v -delete = down Nil - where - down :: List (TreeContext k v) -> k -> Map k v -> Map k v - down ctx _ Leaf = fromZipper ctx Leaf - down ctx k (Two Leaf k1 _ Leaf) - | k == k1 = up ctx Leaf - down ctx k (Two left k1 v1 right) - | k == k1 = let max = maxNode left - in removeMaxNode (Cons (TwoLeft max.key max.value right) ctx) left - | k < k1 = down (Cons (TwoLeft k1 v1 right) ctx) k left - | otherwise = down (Cons (TwoRight left k1 v1) ctx) k right - down ctx k (Three Leaf k1 v1 Leaf k2 v2 Leaf) - | k == k1 = fromZipper ctx (Two Leaf k2 v2 Leaf) - | k == k2 = fromZipper ctx (Two Leaf k1 v1 Leaf) - down ctx k (Three left k1 v1 mid k2 v2 right) - | k == k1 = let max = maxNode left - in removeMaxNode (Cons (ThreeLeft max.key max.value mid k2 v2 right) ctx) left - | k == k2 = let max = maxNode mid - in removeMaxNode (Cons (ThreeMiddle left k1 v1 max.key max.value right) ctx) mid - | k < k1 = down (Cons (ThreeLeft k1 v1 mid k2 v2 right) ctx) k left - | k1 < k && k < k2 = down (Cons (ThreeMiddle left k1 v1 k2 v2 right) ctx) k mid - | otherwise = down (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) k right - - up :: List (TreeContext k v) -> Map k v -> Map k v - up Nil tree = tree - up (Cons (TwoLeft k1 v1 Leaf) ctx) Leaf = fromZipper ctx (Two Leaf k1 v1 Leaf) - up (Cons (TwoRight Leaf k1 v1) ctx) Leaf = fromZipper ctx (Two Leaf k1 v1 Leaf) - up (Cons (TwoLeft k1 v1 (Two m k2 v2 r)) ctx) l = up ctx (Three l k1 v1 m k2 v2 r) - up (Cons (TwoRight (Two l k1 v1 m) k2 v2) ctx) r = up ctx (Three l k1 v1 m k2 v2 r) - up (Cons (TwoLeft k1 v1 (Three b k2 v2 c k3 v3 d)) ctx) a = fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d)) - up (Cons (TwoRight (Three a k1 v1 b k2 v2 c) k3 v3) ctx) d = fromZipper ctx (Two (Two a k1 v1 b) k2 v2 (Two c k3 v3 d)) - up (Cons (ThreeLeft k1 v1 Leaf k2 v2 Leaf) ctx) Leaf = fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf) - up (Cons (ThreeMiddle Leaf k1 v1 k2 v2 Leaf) ctx) Leaf = fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf) - up (Cons (ThreeRight Leaf k1 v1 Leaf k2 v2) ctx) Leaf = fromZipper ctx (Three Leaf k1 v1 Leaf k2 v2 Leaf) - up (Cons (ThreeLeft k1 v1 (Two b k2 v2 c) k3 v3 d) ctx) a = fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d) - up (Cons (ThreeMiddle (Two a k1 v1 b) k2 v2 k3 v3 d) ctx) c = fromZipper ctx (Two (Three a k1 v1 b k2 v2 c) k3 v3 d) - up (Cons (ThreeMiddle a k1 v1 k2 v2 (Two c k3 v3 d)) ctx) b = fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d)) - up (Cons (ThreeRight a k1 v1 (Two b k2 v2 c) k3 v3) ctx) d = fromZipper ctx (Two a k1 v1 (Three b k2 v2 c k3 v3 d)) - up (Cons (ThreeLeft k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4 e) ctx) a = fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e) - up (Cons (ThreeMiddle (Three a k1 v1 b k2 v2 c) k3 v3 k4 v4 e) ctx) d = fromZipper ctx (Three (Two a k1 v1 b) k2 v2 (Two c k3 v3 d) k4 v4 e) - up (Cons (ThreeMiddle a k1 v1 k2 v2 (Three c k3 v3 d k4 v4 e)) ctx) b = fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e)) - up (Cons (ThreeRight a k1 v1 (Three b k2 v2 c k3 v3 d) k4 v4) ctx) e = fromZipper ctx (Three a k1 v1 (Two b k2 v2 c) k3 v3 (Two d k4 v4 e)) - up _ _ = unsafeThrow "Impossible case in 'up'" - - maxNode :: Map k v -> { key :: k, value :: v } - maxNode (Two _ k v Leaf) = { key: k, value: v } - maxNode (Two _ _ _ right) = maxNode right - maxNode (Three _ _ _ _ k v Leaf) = { key: k, value: v } - maxNode (Three _ _ _ _ _ _ right) = maxNode right - maxNode Leaf = unsafeThrow "Impossible case in 'maxNode'" - - - removeMaxNode :: List (TreeContext k v) -> Map k v -> Map k v - removeMaxNode ctx (Two Leaf _ _ Leaf) = up ctx Leaf - removeMaxNode ctx (Two left k v right) = removeMaxNode (Cons (TwoRight left k v) ctx) right - removeMaxNode ctx (Three Leaf k1 v1 Leaf _ _ Leaf) = up (Cons (TwoRight Leaf k1 v1) ctx) Leaf - removeMaxNode ctx (Three left k1 v1 mid k2 v2 right) = removeMaxNode (Cons (ThreeRight left k1 v1 mid k2 v2) ctx) right - removeMaxNode _ Leaf = unsafeThrow "Impossible case in 'removeMaxNode'" - - --- | Insert the value, delete a value, or update a value for a key in a map -alter :: forall k v. (Ord k) => (Maybe v -> Maybe v) -> k -> Map k v -> Map k v -alter f k m = case f (k `lookup` m) of - Nothing -> delete k m - Just v -> insert k v m - --- | Update or delete the value for a key in a map -update :: forall k v. (Ord k) => (v -> Maybe v) -> k -> Map k v -> Map k v -update f k m = alter (maybe Nothing f) k m - --- | Convert any foldable collection of key/value pairs to a map. --- | On key collision, later values take precedence over earlier ones. -fromFoldable :: forall f k v. (Ord k, Foldable f) => f (Tuple k v) -> Map k v -fromFoldable = foldl (\m (Tuple k v) -> insert k v m) empty - --- | Convert any foldable collection of key/value pairs to a map. --- | On key collision, the values are configurably combined. -fromFoldableWith :: forall f k v. (Ord k, Foldable f) => (v -> v -> v) -> f (Tuple k v) -> Map k v -fromFoldableWith f = foldl (\m (Tuple k v) -> alter (combine v) k m) empty where - combine v (Just v') = Just $ f v v' - combine v Nothing = Just v - --- | Convert a map to a list of key/value pairs -toList :: forall k v. Map k v -> List (Tuple k v) -toList Leaf = Nil -toList (Two left k v right) = toList left ++ pure (Tuple k v) ++ toList right -toList (Three left k1 v1 mid k2 v2 right) = toList left ++ pure (Tuple k1 v1) ++ toList mid ++ pure (Tuple k2 v2) ++ toList right - --- | Create a map from a list of key/value pairs -fromList :: forall k v. (Ord k) => List (Tuple k v) -> Map k v -fromList = fromFoldable - --- | Create a map from a list of key/value pairs, using the specified function --- | to combine values for duplicate keys. -fromListWith :: forall k v. (Ord k) => (v -> v -> v) -> List (Tuple k v) -> Map k v -fromListWith = fromFoldableWith - --- | Get a list of the keys contained in a map -keys :: forall k v. Map k v -> List k -keys Leaf = Nil -keys (Two left k _ right) = keys left ++ pure k ++ keys right -keys (Three left k1 _ mid k2 _ right) = keys left ++ pure k1 ++ keys mid ++ pure k2 ++ keys right - --- | Get a list of the values contained in a map -values :: forall k v. Map k v -> List v -values Leaf = Nil -values (Two left _ v right) = values left ++ pure v ++ values right -values (Three left _ v1 mid _ v2 right) = values left ++ pure v1 ++ values mid ++ pure v2 ++ values right - --- | Compute the union of two maps, using the specified function --- | to combine values for duplicate keys. -unionWith :: forall k v. (Ord k) => (v -> v -> v) -> Map k v -> Map k v -> Map k v -unionWith f m1 m2 = foldl go m2 (toList m1) - where - go m (Tuple k v) = alter (Just <<< maybe v (f v)) k m - --- | Compute the union of two maps, preferring values from the first map in the case --- | of duplicate keys -union :: forall k v. (Ord k) => Map k v -> Map k v -> Map k v -union = unionWith const - --- | Compute the union of a collection of maps -unions :: forall k v f. (Ord k, Foldable f) => f (Map k v) -> Map k v -unions = foldl union empty - --- | Calculate the number of key/value pairs in a map -size :: forall k v. Map k v -> Int -size = length <<< values diff --git a/src/Data/StrMap.js b/src/Data/StrMap.js deleted file mode 100644 index 4b8567da..00000000 --- a/src/Data/StrMap.js +++ /dev/null @@ -1,133 +0,0 @@ -/* global exports */ -"use strict"; - -// module Data.StrMap - -exports._copy = function (m) { - var r = {}; - for (var k in m) { - if (m.hasOwnProperty(k)) { - r[k] = m[k]; - } - } - return r; -}; - -exports._copyEff = function (m) { - return function () { - var r = {}; - for (var k in m) { - if (m.hasOwnProperty(k)) { - r[k] = m[k]; - } - } - return r; - }; -}; - -exports.empty = {}; - -exports.runST = function (f) { - return f; -}; - -// jshint maxparams: 2 -exports._fmapStrMap = function (m0, f) { - var m = {}; - for (var k in m0) { - if (m0.hasOwnProperty(k)) { - m[k] = f(m0[k]); - } - } - return m; -}; - -// jshint maxparams: 1 -exports._foldM = function (bind) { - return function (f) { - return function (mz) { - return function (m) { - function g (k) { - return function (z) { - return f(z)(k)(m[k]); - }; - } - for (var k in m) { - if (m.hasOwnProperty(k)) { - mz = bind(mz)(g(k)); - } - } - return mz; - }; - }; - }; -}; - -// jshint maxparams: 4 -exports._foldSCStrMap = function (m, z, f, fromMaybe) { - for (var k in m) { - if (m.hasOwnProperty(k)) { - var maybeR = f(z)(k)(m[k]); - var r = fromMaybe(null)(maybeR); - if (r === null) return z; - else z = r; - } - } - return z; -}; - -// jshint maxparams: 1 -exports.all = function (f) { - return function (m) { - for (var k in m) { - if (m.hasOwnProperty(k) && !f(k)(m[k])) return false; - } - return true; - }; -}; - -exports.size = function (m) { - var s = 0; - for (var k in m) { - if (m.hasOwnProperty(k)) { - ++s; - } - } - return s; -}; - -// jshint maxparams: 4 -exports._lookup = function (no, yes, k, m) { - return k in m ? yes(m[k]) : no; -}; - -// jshint maxparams: 2 -exports._unsafeDeleteStrMap = function (m, k) { - delete m[k]; - return m; -}; - -// jshint maxparams: 4 -exports._lookupST = function (no, yes, k, m) { - return function () { - return k in m ? yes(m[k]) : no; - }; -}; - -function _collect (f) { - return function (m) { - var r = []; - for (var k in m) { - if (m.hasOwnProperty(k)) { - r.push(f(k)(m[k])); - } - } - return r; - }; -} - -exports._collect = _collect; - -exports.keys = Object.keys || _collect(function (k) { - return function () { return k; }; -}); diff --git a/src/Data/StrMap.purs b/src/Data/StrMap.purs deleted file mode 100644 index fcffdf44..00000000 --- a/src/Data/StrMap.purs +++ /dev/null @@ -1,240 +0,0 @@ --- | This module defines a type of native Javascript maps which --- | require the keys to be strings. --- | --- | To maximize performance, Javascript objects are not wrapped, --- | and some native code is used even when it's not necessary. - -module Data.StrMap - ( StrMap() - , empty - , isEmpty - , size - , singleton - , insert - , lookup - , toList - , fromFoldable - , fromFoldableWith - , fromList - , fromListWith - , delete - , member - , alter - , update - , keys - , values - , union - , unions - , isSubmap - , fold - , foldMap - , foldM - , foldMaybe - , all - , thawST - , freezeST - , runST - ) where - -import Prelude - -import Control.Monad.Eff (Eff(), runPure) -import Data.Foldable (Foldable, foldl, foldr, for_) -import Data.Function (Fn2(), runFn2, Fn4(), runFn4) -import Data.Maybe (Maybe(..), maybe, fromMaybe) -import Data.Monoid (Monoid, mempty) -import Data.Traversable (Traversable, traverse) -import Data.Tuple (Tuple(..), uncurry) - -import qualified Data.List as L -import qualified Control.Monad.ST as ST -import qualified Data.StrMap.ST as SM - --- | `StrMap a` represents a map from `String`s to values of type `a`. -foreign import data StrMap :: * -> * - -foreign import _copy :: forall a. StrMap a -> StrMap a - -foreign import _copyEff :: forall a b h r. a -> Eff (st :: ST.ST h | r) b - --- | Convert an immutable map into a mutable map -thawST :: forall a h r. StrMap a -> Eff (st :: ST.ST h | r) (SM.STStrMap h a) -thawST = _copyEff - --- | Convert a mutable map into an immutable map -freezeST :: forall a h r. SM.STStrMap h a -> Eff (st :: ST.ST h | r) (StrMap a) -freezeST = _copyEff - --- | Freeze a mutable map, creating an immutable map. Use this function as you would use --- | `Prelude.runST` to freeze a mutable reference. --- | --- | The rank-2 type prevents the map from escaping the scope of `runST`. -foreign import runST :: forall a r. (forall h. Eff (st :: ST.ST h | r) (SM.STStrMap h a)) -> Eff r (StrMap a) - -pureST :: forall a. (forall h e. Eff (st :: ST.ST h | e) (SM.STStrMap h a)) -> StrMap a -pureST f = runPure (runST f) - -mutate :: forall a b. (forall h e. SM.STStrMap h a -> Eff (st :: ST.ST h | e) b) -> StrMap a -> StrMap a -mutate f m = pureST (do - s <- thawST m - f s - return s) - -foreign import _fmapStrMap :: forall a b. Fn2 (StrMap a) (a -> b) (StrMap b) - -instance functorStrMap :: Functor StrMap where - map f m = runFn2 _fmapStrMap m f - -foreign import _foldM :: forall a m z. (m -> (z -> m) -> m) -> (z -> String -> a -> m) -> m -> StrMap a -> m - --- | Fold the keys and values of a map -fold :: forall a z. (z -> String -> a -> z) -> z -> StrMap a -> z -fold = _foldM ((#)) - --- | Fold the keys and values of a map, accumulating values using --- | some `Monoid`. -foldMap :: forall a m. (Monoid m) => (String -> a -> m) -> StrMap a -> m -foldMap f = fold (\acc k v -> acc <> f k v) mempty - --- | Fold the keys and values of a map, accumulating values and effects in --- | some `Monad`. -foldM :: forall a m z. (Monad m) => (z -> String -> a -> m z) -> z -> StrMap a -> m z -foldM f z = _foldM (>>=) f (pure z) - -instance foldableStrMap :: Foldable StrMap where - foldl f = fold (\z _ -> f z) - foldr f z m = foldr f z (values m) - foldMap f = foldMap (const f) - -instance traversableStrMap :: Traversable StrMap where - traverse f ms = foldr (\x acc -> union <$> x <*> acc) (pure empty) ((map (uncurry singleton)) <$> (traverse f <$> toList ms)) - sequence = traverse id - --- Unfortunately the above are not short-circuitable (consider using purescript-machines) --- so we need special cases: - -foreign import _foldSCStrMap :: forall a z. Fn4 (StrMap a) z (z -> String -> a -> Maybe z) (forall b. b -> Maybe b -> b) z - --- | Fold the keys and values of a map. --- | --- | This function allows the folding function to terminate the fold early, --- | using `Maybe`. -foldMaybe :: forall a z. (z -> String -> a -> Maybe z) -> z -> StrMap a -> z -foldMaybe f z m = runFn4 _foldSCStrMap m z f fromMaybe - --- | Test whether all key/value pairs in a `StrMap` satisfy a predicate. -foreign import all :: forall a. (String -> a -> Boolean) -> StrMap a -> Boolean - -instance eqStrMap :: (Eq a) => Eq (StrMap a) where - eq m1 m2 = (isSubmap m1 m2) && (isSubmap m2 m1) - -instance showStrMap :: (Show a) => Show (StrMap a) where - show m = "fromList " ++ show (toList m) - --- | An empty map -foreign import empty :: forall a. StrMap a - --- | Test whether one map contains all of the keys and values contained in another map -isSubmap :: forall a. (Eq a) => StrMap a -> StrMap a -> Boolean -isSubmap m1 m2 = all f m1 where - f k v = runFn4 _lookup false ((==) v) k m2 - --- | Test whether a map is empty -isEmpty :: forall a. StrMap a -> Boolean -isEmpty = all (\_ _ -> false) - --- | Calculate the number of key/value pairs in a map -foreign import size :: forall a. StrMap a -> Number - --- | Create a map with one key/value pair -singleton :: forall a. String -> a -> StrMap a -singleton k v = pureST (do - s <- SM.new - SM.poke s k v - return s) - -foreign import _lookup :: forall a z. Fn4 z (a -> z) String (StrMap a) z - --- | Lookup the value for a key in a map -lookup :: forall a. String -> StrMap a -> Maybe a -lookup = runFn4 _lookup Nothing Just - --- | Test whether a `String` appears as a key in a map -member :: forall a. String -> StrMap a -> Boolean -member = runFn4 _lookup false (const true) - --- | Insert a key and value into a map -insert :: forall a. String -> a -> StrMap a -> StrMap a -insert k v = mutate (\s -> SM.poke s k v) - -foreign import _unsafeDeleteStrMap :: forall a. Fn2 (StrMap a) String (StrMap a) - --- | Delete a key and value from a map -delete :: forall a. String -> StrMap a -> StrMap a -delete k = mutate (\s -> SM.delete s k) - --- | Insert, remove or update a value for a key in a map -alter :: forall a. (Maybe a -> Maybe a) -> String -> StrMap a -> StrMap a -alter f k m = case f (k `lookup` m) of - Nothing -> delete k m - Just v -> insert k v m - --- | Remove or update a value for a key in a map -update :: forall a. (a -> Maybe a) -> String -> StrMap a -> StrMap a -update f k m = alter (maybe Nothing f) k m - --- | Create a map from a foldable collection of key/value pairs -fromFoldable :: forall f a. (Foldable f) => - f (Tuple String a) -> StrMap a -fromFoldable l = pureST (do - s <- SM.new - for_ l (\(Tuple k v) -> SM.poke s k v) - return s) - -foreign import _lookupST :: forall a h r z. Fn4 z (a -> z) String (SM.STStrMap h a) (Eff (st :: ST.ST h | r) z) - --- | Create a map from a foldable collection of key/value pairs, using the --- | specified function to combine values for duplicate keys. -fromFoldableWith :: forall f a. (Foldable f) => - (a -> a -> a) -> f (Tuple String a) -> StrMap a -fromFoldableWith f l = pureST (do - s <- SM.new - for_ l (\(Tuple k v) -> runFn4 _lookupST v (f v) k s >>= SM.poke s k) - return s) - --- | Create a map from a list of key/value pairs -fromList :: forall a. L.List (Tuple String a) -> StrMap a -fromList = fromFoldable - --- | Create a map from a list of key/value pairs, using the specified function --- | to combine values for duplicate keys. -fromListWith :: forall a. (a -> a -> a) -> L.List (Tuple String a) -> StrMap a -fromListWith = fromFoldableWith - -foreign import _collect :: forall a b . (String -> a -> b) -> StrMap a -> Array b - --- | Convert a map into a list of key/value pairs -toList :: forall a. StrMap a -> L.List (Tuple String a) -toList = L.toList <<< _collect Tuple - --- | Get an array of the keys in a map -foreign import keys :: forall a. StrMap a -> Array String - --- | Get a list of the values in a map -values :: forall a. StrMap a -> L.List a -values = L.toList <<< _collect (\_ v -> v) - --- | Compute the union of two maps, preferring the first map in the case of --- | duplicate keys. -union :: forall a. StrMap a -> StrMap a -> StrMap a -union m = mutate (\s -> foldM SM.poke s m) - --- | Compute the union of a collection of maps -unions :: forall a. L.List (StrMap a) -> StrMap a -unions = foldl union empty - -instance semigroupStrMap :: (Semigroup a) => Semigroup (StrMap a) where - append m1 m2 = mutate (\s1 -> foldM (\s2 k v2 -> SM.poke s2 k (runFn4 _lookup v2 (\v1 -> v1 <> v2) k m2)) s1 m1) m2 - -instance monoidStrMap :: (Semigroup a) => Monoid (StrMap a) where - mempty = empty diff --git a/src/Data/StrMap/ST.js b/src/Data/StrMap/ST.js deleted file mode 100644 index bc0a0e47..00000000 --- a/src/Data/StrMap/ST.js +++ /dev/null @@ -1,40 +0,0 @@ -/* global exports */ -"use strict"; - -// module Data.StrMap.ST - -exports["new"] = function () { - return {}; -}; - -exports.peekImpl = function (just) { - return function (nothing) { - return function (m) { - return function (k) { - return function () { - return {}.hasOwnProperty.call(m, k) ? just(m[k]) : nothing; - }; - }; - }; - }; -}; - -exports.poke = function (m) { - return function (k) { - return function (v) { - return function () { - m[k] = v; - return m; - }; - }; - }; -}; - -exports["delete"] = function (m) { - return function (k) { - return function () { - delete m[k]; - return m; - }; - }; -}; diff --git a/src/Data/StrMap/ST.purs b/src/Data/StrMap/ST.purs deleted file mode 100644 index a13ed955..00000000 --- a/src/Data/StrMap/ST.purs +++ /dev/null @@ -1,39 +0,0 @@ --- | Helper functions for working with mutable maps using the `ST` effect. --- | --- | This module can be used when performance is important and mutation is a local effect. - -module Data.StrMap.ST - ( STStrMap() - , new - , peek - , poke - , delete - ) where - -import Prelude - -import Control.Monad.Eff (Eff()) -import Control.Monad.ST (ST()) -import Data.Maybe (Maybe(..)) - --- | A reference to a mutable map --- | --- | The first type parameter represents the memory region which the map belongs to. The second type parameter defines the type of elements of the mutable array. --- | --- | The runtime representation of a value of type `STStrMap h a` is the same as that of `StrMap a`, except that mutation is allowed. -foreign import data STStrMap :: * -> * -> * - --- | Create a new, empty mutable map -foreign import new :: forall a h r. Eff (st :: ST h | r) (STStrMap h a) - --- | Get the value for a key in a mutable map -peek :: forall a h r. STStrMap h a -> String -> Eff (st :: ST h | r) (Maybe a) -peek = peekImpl Just Nothing - -foreign import peekImpl :: forall a b h r. (a -> b) -> b -> STStrMap h a -> String -> Eff (st :: ST h | r) b - --- | Update the value for a key in a mutable map -foreign import poke :: forall a h r. STStrMap h a -> String -> a -> Eff (st :: ST h | r) (STStrMap h a) - --- | Remove a key and the corresponding value from a mutable map -foreign import delete :: forall a h r. STStrMap h a -> String -> Eff (st :: ST h | r) (STStrMap h a) diff --git a/src/Data/StrMap/ST/Unsafe.js b/src/Data/StrMap/ST/Unsafe.js deleted file mode 100644 index b18005f2..00000000 --- a/src/Data/StrMap/ST/Unsafe.js +++ /dev/null @@ -1,10 +0,0 @@ -/* global exports */ -"use strict"; - -// module Data.StrMap.ST.Unsafe - -exports.unsafeGet = function (m) { - return function () { - return m; - }; -}; diff --git a/src/Data/StrMap/ST/Unsafe.purs b/src/Data/StrMap/ST/Unsafe.purs deleted file mode 100644 index 1ad27016..00000000 --- a/src/Data/StrMap/ST/Unsafe.purs +++ /dev/null @@ -1,15 +0,0 @@ -module Data.StrMap.ST.Unsafe - ( unsafeGet - ) where - -import Prelude - -import Control.Monad.Eff (Eff()) -import Control.Monad.ST (ST()) -import Data.StrMap (StrMap()) -import Data.StrMap.ST (STStrMap()) - --- | Unsafely get the map out of ST without copying it --- | --- | If you later change the ST version of the map the pure value will also change. -foreign import unsafeGet :: forall a h r. STStrMap h a -> Eff (st :: ST h | r) (StrMap a) diff --git a/src/Data/StrMap/Unsafe.js b/src/Data/StrMap/Unsafe.js deleted file mode 100644 index 40c9e19c..00000000 --- a/src/Data/StrMap/Unsafe.js +++ /dev/null @@ -1,10 +0,0 @@ -/* global exports */ -"use strict"; - -// module Data.StrMap.Unsafe - -exports.unsafeIndex = function (m) { - return function (k) { - return m[k]; - }; -}; diff --git a/src/Data/StrMap/Unsafe.purs b/src/Data/StrMap/Unsafe.purs deleted file mode 100644 index 137e7226..00000000 --- a/src/Data/StrMap/Unsafe.purs +++ /dev/null @@ -1,12 +0,0 @@ -module Data.StrMap.Unsafe - ( unsafeIndex - ) where - -import Prelude - -import Data.StrMap (StrMap()) - --- | Unsafely get the value for a key in a map. --- | --- | This function does not check whether the key exists in the map. -foreign import unsafeIndex :: forall a. StrMap a -> String -> a diff --git a/test/Test/Data/Map.purs b/test/Test/Data/Map.purs deleted file mode 100644 index 99e40342..00000000 --- a/test/Test/Data/Map.purs +++ /dev/null @@ -1,236 +0,0 @@ -module Test.Data.Map where - -import Prelude - -import Control.Alt ((<|>)) -import Control.Monad.Eff.Console (log) -import Data.Foldable (foldl, for_) -import Data.Function (on) -import Data.List (List(..), groupBy, length, nubBy, sortBy, singleton, toList) -import Data.Maybe (Maybe(..), fromMaybe) -import Data.Maybe.Unsafe (unsafeThrow) -import Data.Tuple (Tuple(..), fst) -import Test.QuickCheck ((), quickCheck, quickCheck') -import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary) - -import qualified Data.Map as M - -newtype TestMap k v = TestMap (M.Map k v) - -instance arbTestMap :: (Eq k, Ord k, Arbitrary k, Arbitrary v) => Arbitrary (TestMap k v) where - arbitrary = TestMap <<< M.fromList <$> arbitrary - -data SmallKey = A | B | C | D | E | F | G | H | I | J - -instance showSmallKey :: Show SmallKey where - show A = "A" - show B = "B" - show C = "C" - show D = "D" - show E = "E" - show F = "F" - show G = "G" - show H = "H" - show I = "I" - show J = "J" - -instance eqSmallKey :: Eq SmallKey where - eq A A = true - eq B B = true - eq C C = true - eq D D = true - eq E E = true - eq F F = true - eq G G = true - eq H H = true - eq I I = true - eq J J = true - eq _ _ = false - -smallKeyToInt :: SmallKey -> Int -smallKeyToInt A = 0 -smallKeyToInt B = 1 -smallKeyToInt C = 2 -smallKeyToInt D = 3 -smallKeyToInt E = 4 -smallKeyToInt F = 5 -smallKeyToInt G = 6 -smallKeyToInt H = 7 -smallKeyToInt I = 8 -smallKeyToInt J = 9 - -instance ordSmallKey :: Ord SmallKey where - compare = compare `on` smallKeyToInt - -instance arbSmallKey :: Arbitrary SmallKey where - arbitrary = do - n <- arbitrary - return case n of - _ | n < 0.1 -> A - _ | n < 0.2 -> B - _ | n < 0.3 -> C - _ | n < 0.4 -> D - _ | n < 0.5 -> E - _ | n < 0.6 -> F - _ | n < 0.7 -> G - _ | n < 0.8 -> H - _ | n < 0.9 -> I - _ -> J - -data Instruction k v = Insert k v | Delete k - -instance showInstruction :: (Show k, Show v) => Show (Instruction k v) where - show (Insert k v) = "Insert (" ++ show k ++ ") (" ++ show v ++ ")" - show (Delete k) = "Delete (" ++ show k ++ ")" - -instance arbInstruction :: (Arbitrary k, Arbitrary v) => Arbitrary (Instruction k v) where - arbitrary = do - b <- arbitrary - case b of - true -> do - k <- arbitrary - v <- arbitrary - return (Insert k v) - false -> do - k <- arbitrary - return (Delete k) - -runInstructions :: forall k v. (Ord k) => List (Instruction k v) -> M.Map k v -> M.Map k v -runInstructions instrs t0 = foldl step t0 instrs - where - step tree (Insert k v) = M.insert k v tree - step tree (Delete k) = M.delete k tree - -smallKey :: SmallKey -> SmallKey -smallKey k = k - -number :: Int -> Int -number n = n - -mapTests = do - - -- Data.Map - - log "Test inserting into empty tree" - quickCheck $ \k v -> M.lookup (smallKey k) (M.insert k v M.empty) == Just (number v) - ("k: " ++ show k ++ ", v: " ++ show v) - - log "Test delete after inserting" - quickCheck $ \k v -> M.isEmpty (M.delete (smallKey k) (M.insert k (number v) M.empty)) - ("k: " ++ show k ++ ", v: " ++ show v) - - log "Insert two, lookup first" - quickCheck $ \k1 v1 k2 v2 -> k1 == k2 || M.lookup k1 (M.insert (smallKey k2) (number v2) (M.insert (smallKey k1) (number v1) M.empty)) == Just v1 - ("k1: " ++ show k1 ++ ", v1: " ++ show v1 ++ ", k2: " ++ show k2 ++ ", v2: " ++ show v2) - - log "Insert two, lookup second" - quickCheck $ \k1 v1 k2 v2 -> M.lookup k2 (M.insert (smallKey k2) (number v2) (M.insert (smallKey k1) (number v1) M.empty)) == Just v2 - ("k1: " ++ show k1 ++ ", v1: " ++ show v1 ++ ", k2: " ++ show k2 ++ ", v2: " ++ show v2) - - log "Insert two, delete one" - quickCheck $ \k1 v1 k2 v2 -> k1 == k2 || M.lookup k2 (M.delete k1 (M.insert (smallKey k2) (number v2) (M.insert (smallKey k1) (number v1) M.empty))) == Just v2 - ("k1: " ++ show k1 ++ ", v1: " ++ show v1 ++ ", k2: " ++ show k2 ++ ", v2: " ++ show v2) - - log "Check balance property" - quickCheck' 1000 $ \instrs -> - let - tree :: M.Map SmallKey Int - tree = runInstructions instrs M.empty - in M.checkValid tree ("Map not balanced:\n " ++ show tree ++ "\nGenerated by:\n " ++ show instrs) - - log "Lookup from empty" - quickCheck $ \k -> M.lookup k (M.empty :: M.Map SmallKey Int) == Nothing - - log "Lookup from singleton" - quickCheck $ \k v -> M.lookup (k :: SmallKey) (M.singleton k (v :: Int)) == Just v - - log "Random lookup" - quickCheck' 1000 $ \instrs k v -> - let - tree :: M.Map SmallKey Int - tree = M.insert k v (runInstructions instrs M.empty) - in M.lookup k tree == Just v ("instrs:\n " ++ show instrs ++ "\nk:\n " ++ show k ++ "\nv:\n " ++ show v) - - log "Singleton to list" - quickCheck $ \k v -> M.toList (M.singleton k v :: M.Map SmallKey Int) == singleton (Tuple k v) - - log "fromFoldable [] = empty" - quickCheck (M.fromFoldable [] == (M.empty :: M.Map Unit Unit) - "was not empty") - - log "fromFoldable & key collision" - do - let nums = M.fromFoldable [Tuple 0 "zero", Tuple 1 "what", Tuple 1 "one"] - quickCheck (M.lookup 0 nums == Just "zero" "invalid lookup - 0") - quickCheck (M.lookup 1 nums == Just "one" "invalid lookup - 1") - quickCheck (M.lookup 2 nums == Nothing "invalid lookup - 2") - - log "fromFoldableWith const [] = empty" - quickCheck (M.fromFoldableWith const [] == (M.empty :: M.Map Unit Unit) - "was not empty") - - log "fromFoldableWith (+) & key collision" - do - let nums = M.fromFoldableWith (+) [Tuple 0 1, Tuple 1 1, Tuple 1 1] - quickCheck (M.lookup 0 nums == Just 1 "invalid lookup - 0") - quickCheck (M.lookup 1 nums == Just 2 "invalid lookup - 1") - quickCheck (M.lookup 2 nums == Nothing "invalid lookup - 2") - - log "toList . fromList = id" - quickCheck $ \arr -> let f x = M.toList (M.fromList x) - in f (f arr) == f (arr :: List (Tuple SmallKey Int)) show arr - - log "fromList . toList = id" - quickCheck $ \(TestMap m) -> let f m = M.fromList (M.toList m) in - M.toList (f m) == M.toList (m :: M.Map SmallKey Int) show m - - log "fromListWith const = fromList" - quickCheck $ \arr -> M.fromListWith const arr == - M.fromList (arr :: List (Tuple SmallKey Int)) show arr - - log "fromListWith (<>) = fromList . collapse with (<>) . group on fst" - quickCheck $ \arr -> - let combine (Tuple s a) (Tuple t b) = (Tuple s $ b <> a) - foldl1 g (Cons x xs) = foldl g x xs - foldl1 _ Nil = unsafeThrow "Impossible case in 'foldl1'" - f = M.fromList <<< (<$>) (foldl1 combine) <<< - groupBy ((==) `on` fst) <<< sortBy (compare `on` fst) in - M.fromListWith (<>) arr == f (arr :: List (Tuple String String)) show arr - - log "Lookup from union" - quickCheck $ \(TestMap m1) (TestMap m2) k -> - M.lookup (smallKey k) (M.union m1 m2) == (case M.lookup k m1 of - Nothing -> M.lookup k m2 - Just v -> Just (number v)) ("m1: " ++ show m1 ++ ", m2: " ++ show m2 ++ ", k: " ++ show k ++ ", v1: " ++ show (M.lookup k m1) ++ ", v2: " ++ show (M.lookup k m2) ++ ", union: " ++ show (M.union m1 m2)) - - log "Union is idempotent" - quickCheck $ \(TestMap m1) (TestMap m2) -> (m1 `M.union` m2) == ((m1 `M.union` m2) `M.union` (m2 :: M.Map SmallKey Int)) - - log "Union prefers left" - quickCheck $ \(TestMap m1) (TestMap m2) k -> M.lookup k (M.union m1 (m2 :: M.Map SmallKey Int)) == (M.lookup k m1 <|> M.lookup k m2) - - log "unionWith" - for_ [Tuple (+) 0, Tuple (*) 1] $ \(Tuple op ident) -> - quickCheck $ \(TestMap m1) (TestMap m2) k -> - let u = M.unionWith op m1 m2 :: M.Map SmallKey Int - in case M.lookup k u of - Nothing -> not (M.member k m1 || M.member k m2) - Just v -> v == op (fromMaybe ident (M.lookup k m1)) (fromMaybe ident (M.lookup k m2)) - - log "unionWith argument order" - quickCheck $ \(TestMap m1) (TestMap m2) k -> - let u = M.unionWith (-) m1 m2 :: M.Map SmallKey Int - in1 = M.member k m1 - v1 = M.lookup k m1 - in2 = M.member k m2 - v2 = M.lookup k m2 - in case M.lookup k u of - Just v | in1 && in2 -> Just v == ((-) <$> v1 <*> v2) - Just v | in1 -> Just v == v1 - Just v -> Just v == v2 - Nothing -> not (in1 || in2) - - log "size" - quickCheck $ \xs -> - let xs' = nubBy ((==) `on` fst) xs - in M.size (M.fromList xs') == length (xs' :: List (Tuple SmallKey Int)) diff --git a/test/Test/Data/StrMap.purs b/test/Test/Data/StrMap.purs deleted file mode 100644 index 021b578b..00000000 --- a/test/Test/Data/StrMap.purs +++ /dev/null @@ -1,140 +0,0 @@ -module Test.Data.StrMap where - -import Prelude - -import Data.List (List(..), groupBy, sortBy, singleton, toList, zipWith) -import Data.Foldable (foldl) -import Data.Function (on) -import Data.Maybe (Maybe(..)) -import Data.Maybe.Unsafe (unsafeThrow) -import Data.Tuple (Tuple(..), fst) -import Control.Monad.Eff.Console (log) -import Test.QuickCheck ((), quickCheck, quickCheck') -import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary) -import qualified Data.String as S -import qualified Data.StrMap as M - -newtype TestStrMap v = TestStrMap (M.StrMap v) - -instance arbTestStrMap :: (Arbitrary v) => Arbitrary (TestStrMap v) where - arbitrary = TestStrMap <<< M.fromList <$> arbitrary - -data Instruction k v = Insert k v | Delete k - -instance showInstruction :: (Show k, Show v) => Show (Instruction k v) where - show (Insert k v) = "Insert (" ++ show k ++ ") (" ++ show v ++ ")" - show (Delete k) = "Delete (" ++ show k ++ ")" - -instance arbInstruction :: (Arbitrary v) => Arbitrary (Instruction String v) where - arbitrary = do - b <- arbitrary - k <- arbitrary - case b of - true -> do - v <- arbitrary - return (Insert k v) - false -> do - return (Delete k) - -runInstructions :: forall v. List (Instruction String v) -> M.StrMap v -> M.StrMap v -runInstructions instrs t0 = foldl step t0 instrs - where - step tree (Insert k v) = M.insert k v tree - step tree (Delete k) = M.delete k tree - -number :: Int -> Int -number n = n - -strMapTests = do - log "Test inserting into empty tree" - quickCheck $ \k v -> M.lookup k (M.insert k v M.empty) == Just (number v) - ("k: " ++ show k ++ ", v: " ++ show v) - - log "Test delete after inserting" - quickCheck $ \k v -> M.isEmpty (M.delete k (M.insert k (number v) M.empty)) - ("k: " ++ show k ++ ", v: " ++ show v) - - log "Insert two, lookup first" - quickCheck $ \k1 v1 k2 v2 -> k1 == k2 || M.lookup k1 (M.insert k2 (number v2) (M.insert k1 (number v1) M.empty)) == Just v1 - ("k1: " ++ show k1 ++ ", v1: " ++ show v1 ++ ", k2: " ++ show k2 ++ ", v2: " ++ show v2) - - log "Insert two, lookup second" - quickCheck $ \k1 v1 k2 v2 -> M.lookup k2 (M.insert k2 (number v2) (M.insert k1 (number v1) M.empty)) == Just v2 - ("k1: " ++ show k1 ++ ", v1: " ++ show v1 ++ ", k2: " ++ show k2 ++ ", v2: " ++ show v2) - - log "Insert two, delete one" - quickCheck $ \k1 v1 k2 v2 -> k1 == k2 || M.lookup k2 (M.delete k1 (M.insert k2 (number v2) (M.insert k1 (number v1) M.empty))) == Just v2 - ("k1: " ++ show k1 ++ ", v1: " ++ show v1 ++ ", k2: " ++ show k2 ++ ", v2: " ++ show v2) - - log "Lookup from empty" - quickCheck $ \k -> M.lookup k (M.empty :: M.StrMap Int) == Nothing - - log "Lookup from singleton" - quickCheck $ \k v -> M.lookup k (M.singleton k (v :: Int)) == Just v - - log "Random lookup" - quickCheck' 1000 $ \instrs k v -> - let - tree :: M.StrMap Int - tree = M.insert k v (runInstructions instrs M.empty) - in M.lookup k tree == Just v ("instrs:\n " ++ show instrs ++ "\nk:\n " ++ show k ++ "\nv:\n " ++ show v) - - log "Singleton to list" - quickCheck $ \k v -> M.toList (M.singleton k v :: M.StrMap Int) == singleton (Tuple k v) - - log "fromFoldable [] = empty" - quickCheck (M.fromFoldable [] == (M.empty :: M.StrMap Unit) - "was not empty") - - log "fromFoldable & key collision" - do - let nums = M.fromFoldable [Tuple "0" "zero", Tuple "1" "what", Tuple "1" "one"] - quickCheck (M.lookup "0" nums == Just "zero" "invalid lookup - 0") - quickCheck (M.lookup "1" nums == Just "one" "invalid lookup - 1") - quickCheck (M.lookup "2" nums == Nothing "invalid lookup - 2") - - log "fromFoldableWith const [] = empty" - quickCheck (M.fromFoldableWith const [] == (M.empty :: M.StrMap Unit) - "was not empty") - - log "fromFoldableWith (+) & key collision" - do - let nums = M.fromFoldableWith (+) [Tuple "0" 1, Tuple "1" 1, Tuple "1" 1] - quickCheck (M.lookup "0" nums == Just 1 "invalid lookup - 0") - quickCheck (M.lookup "1" nums == Just 2 "invalid lookup - 1") - quickCheck (M.lookup "2" nums == Nothing "invalid lookup - 2") - - log "toList . fromList = id" - quickCheck $ \arr -> let f x = M.toList (M.fromList x) - in f (f arr) == f (arr :: List (Tuple String Int)) show arr - - log "fromList . toList = id" - quickCheck $ \(TestStrMap m) -> - let f m = M.fromList (M.toList m) in - M.toList (f m) == M.toList (m :: M.StrMap Int) show m - - log "fromListWith const = fromList" - quickCheck $ \arr -> M.fromListWith const arr == - M.fromList (arr :: List (Tuple String Int)) show arr - - log "fromListWith (<>) = fromList . collapse with (<>) . group on fst" - quickCheck $ \arr -> - let combine (Tuple s a) (Tuple t b) = (Tuple s $ b <> a) - foldl1 g (Cons x xs) = foldl g x xs - foldl1 _ Nil = unsafeThrow "Impossible case in 'foldl1'" - f = M.fromList <<< (<$>) (foldl1 combine) <<< - groupBy ((==) `on` fst) <<< sortBy (compare `on` fst) in - M.fromListWith (<>) arr == f (arr :: List (Tuple String String)) show arr - - log "Lookup from union" - quickCheck $ \(TestStrMap m1) (TestStrMap m2) k -> - M.lookup k (M.union m1 m2) == (case M.lookup k m1 of - Nothing -> M.lookup k m2 - Just v -> Just (number v)) ("m1: " ++ show m1 ++ ", m2: " ++ show m2 ++ ", k: " ++ show k ++ ", v1: " ++ show (M.lookup k m1) ++ ", v2: " ++ show (M.lookup k m2) ++ ", union: " ++ show (M.union m1 m2)) - - log "Union is idempotent" - quickCheck $ \(TestStrMap m1) (TestStrMap m2) -> - (m1 `M.union` m2) == ((m1 `M.union` m2) `M.union` (m2 :: M.StrMap Int)) (show (M.size (m1 `M.union` m2)) ++ " != " ++ show (M.size ((m1 `M.union` m2) `M.union` m2))) - - log "toList = zip keys values" - quickCheck $ \(TestStrMap m) -> M.toList m == zipWith Tuple (toList $ M.keys m) (M.values m :: List Int) diff --git a/test/Test/Main.purs b/test/Test/Main.purs deleted file mode 100644 index 814d8713..00000000 --- a/test/Test/Main.purs +++ /dev/null @@ -1,15 +0,0 @@ -module Test.Main where - -import Prelude - -import Control.Monad.Eff.Console (log) - -import Test.Data.Map (mapTests) -import Test.Data.StrMap (strMapTests) - -main = do - log "Running Map tests" - mapTests - - log "Running StrMap tests" - strMapTests