Skip to content

Commit 05fd62f

Browse files
committed
removes StrMap, adds Set
1 parent 480a65a commit 05fd62f

File tree

18 files changed

+230
-867
lines changed

18 files changed

+230
-867
lines changed

bench/Bench/Data/Map.purs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
module Bench.Data.Map where
22

33
import Prelude
4-
import Control.Monad.Eff (Eff)
5-
import Control.Monad.Eff.Console (CONSOLE, log)
6-
import Performance.Minibench (bench, benchWith)
74

8-
import Data.Tuple (Tuple(..))
95
import Data.List as L
106
import Data.Map as M
7+
import Data.Tuple (Tuple(..))
8+
import Effect (Effect)
9+
import Effect.Console (log)
10+
import Performance.Minibench (bench, benchWith)
1111

12-
benchMap :: Eff (console :: CONSOLE) Unit
12+
benchMap :: Effect Unit
1313
benchMap = do
1414
log "size"
1515
log "---------------"

bench/Bench/Data/StrMap.purs

Lines changed: 0 additions & 27 deletions
This file was deleted.

bench/Bench/Main.purs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
11
module Bench.Main where
22

33
import Prelude
4-
import Control.Monad.Eff (Eff)
5-
import Control.Monad.Eff.Console (CONSOLE, log)
64

75
import Bench.Data.Map (benchMap)
8-
import Bench.Data.StrMap (benchStrMap)
6+
import Effect (Effect)
7+
import Effect.Console (log)
98

10-
main :: Eff (console :: CONSOLE) Unit
9+
main :: Effect Unit
1110
main = do
1211
log "Map"
1312
log "==="
1413
benchMap
15-
16-
log ""
17-
18-
19-
log "StrMap"
20-
log "======"
21-
benchStrMap

bower.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
"purescript-foldable-traversable": "#compiler/0.12"
3030
},
3131
"devDependencies": {
32-
"purescript-quickcheck": "^4.0.0",
33-
"purescript-minibench": "^1.0.0"
32+
"purescript-quickcheck": "#compiler/0.12",
33+
"purescript-minibench": "#compiler/0.12",
34+
"purescript-console": "#compiler/0.12",
35+
"purescript-assert": "#compiler/0.12"
3436
}
3537
}

src/Data/Set.purs

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
-- | This module defines a type of sets as balanced 2-3 trees, based on
2+
-- | <http://www.cs.princeton.edu/~dpw/courses/cos326-12/ass/2-3-trees.pdf>
3+
-- |
4+
-- | Qualified import is encouraged, so as to avoid name clashes with other modules.
5+
6+
module Data.Set
7+
( Set
8+
, fromFoldable
9+
, toUnfoldable
10+
, empty
11+
, isEmpty
12+
, singleton
13+
, map
14+
, checkValid
15+
, insert
16+
, member
17+
, delete
18+
, size
19+
, findMin
20+
, findMax
21+
, union
22+
, unions
23+
, difference
24+
, subset
25+
, properSubset
26+
, intersection
27+
) where
28+
29+
import Prelude hiding (map)
30+
31+
import Control.Monad.Rec.Class (Step(..), tailRecM2)
32+
import Control.Monad.ST (ST)
33+
import Control.Monad.ST as ST
34+
import Data.Array as Array
35+
import Data.Array.ST (STArray, emptySTArray, pushSTArray, unsafeFreeze)
36+
import Data.Eq (class Eq1)
37+
import Data.Foldable (class Foldable, foldMap, foldl, foldr)
38+
import Data.List (List)
39+
import Data.List as List
40+
import Data.Map as M
41+
import Data.Maybe (Maybe)
42+
import Data.Ord (class Ord1)
43+
import Data.Unfoldable (class Unfoldable)
44+
import Partial.Unsafe (unsafePartial)
45+
import Prelude as Prelude
46+
47+
-- | `Set a` represents a set of values of type `a`
48+
data Set a = Set (M.Map a Unit)
49+
50+
-- | Create a set from a foldable structure.
51+
fromFoldable :: forall f a. Foldable f => Ord a => f a -> Set a
52+
fromFoldable = foldl (\m a -> insert a m) empty
53+
54+
-- | Convert a set to an unfoldable structure.
55+
toUnfoldable :: forall f a. Unfoldable f => Set a -> f a
56+
toUnfoldable = List.toUnfoldable <<< toList
57+
58+
toList :: forall a. Set a -> List a
59+
toList (Set m) = M.keys m
60+
61+
instance eqSet :: Eq a => Eq (Set a) where
62+
eq (Set m1) (Set m2) = m1 == m2
63+
64+
instance eq1Set :: Eq1 Set where
65+
eq1 = eq
66+
67+
instance showSet :: Show a => Show (Set a) where
68+
show s = "(fromFoldable " <> show (toList s) <> ")"
69+
70+
instance ordSet :: Ord a => Ord (Set a) where
71+
compare s1 s2 = compare (toList s1) (toList s2)
72+
73+
instance ord1Set :: Ord1 Set where
74+
compare1 = compare
75+
76+
instance monoidSet :: Ord a => Monoid (Set a) where
77+
mempty = empty
78+
79+
instance semigroupSet :: Ord a => Semigroup (Set a) where
80+
append = union
81+
82+
instance foldableSet :: Foldable Set where
83+
foldMap f = foldMap f <<< toList
84+
foldl f x = foldl f x <<< toList
85+
foldr f x = foldr f x <<< toList
86+
87+
-- | An empty set
88+
empty :: forall a. Set a
89+
empty = Set M.empty
90+
91+
-- | Test if a set is empty
92+
isEmpty :: forall a. Set a -> Boolean
93+
isEmpty (Set m) = M.isEmpty m
94+
95+
-- | Create a set with one element
96+
singleton :: forall a. a -> Set a
97+
singleton a = Set (M.singleton a unit)
98+
99+
-- | Maps over the values in a set.
100+
-- |
101+
-- | This operation is not structure-preserving for sets, so is not a valid
102+
-- | `Functor`. An example case: mapping `const x` over a set with `n > 0`
103+
-- | elements will result in a set with one element.
104+
map :: forall a b. Ord b => (a -> b) -> Set a -> Set b
105+
map f = foldl (\m a -> insert (f a) m) empty
106+
107+
-- | Check whether the underlying tree satisfies the 2-3 invariant
108+
-- |
109+
-- | This function is provided for internal use.
110+
checkValid :: forall a. Set a -> Boolean
111+
checkValid (Set m) = M.checkValid m
112+
113+
-- | Test if a value is a member of a set
114+
member :: forall a. Ord a => a -> Set a -> Boolean
115+
member a (Set m) = a `M.member` m
116+
117+
-- | Insert a value into a set
118+
insert :: forall a. Ord a => a -> Set a -> Set a
119+
insert a (Set m) = Set (M.insert a unit m)
120+
121+
-- | Delete a value from a set
122+
delete :: forall a. Ord a => a -> Set a -> Set a
123+
delete a (Set m) = Set (a `M.delete` m)
124+
125+
-- | Find the size of a set
126+
size :: forall a. Set a -> Int
127+
size (Set m) = M.size m
128+
129+
findMin :: forall a. Set a -> Maybe a
130+
findMin (Set m) = Prelude.map _.key (M.findMin m)
131+
132+
findMax :: forall a. Set a -> Maybe a
133+
findMax (Set m) = Prelude.map _.key (M.findMax m)
134+
135+
-- | Form the union of two sets
136+
-- |
137+
-- | Running time: `O(n * log(m))`
138+
union :: forall a. Ord a => Set a -> Set a -> Set a
139+
union (Set m1) (Set m2) = Set (m1 `M.union` m2)
140+
141+
-- | Form the union of a collection of sets
142+
unions :: forall f a. Foldable f => Ord a => f (Set a) -> Set a
143+
unions = foldl union empty
144+
145+
-- | Form the set difference
146+
difference :: forall a. Ord a => Set a -> Set a -> Set a
147+
difference s1 s2 = foldl (flip delete) s1 (toList s2)
148+
149+
-- | True if and only if every element in the first set
150+
-- | is an element of the second set
151+
subset :: forall a. Ord a => Set a -> Set a -> Boolean
152+
subset s1 s2 = isEmpty $ s1 `difference` s2
153+
154+
-- | True if and only if the first set is a subset of the second set
155+
-- | and the sets are not equal
156+
properSubset :: forall a. Ord a => Set a -> Set a -> Boolean
157+
properSubset s1 s2 = subset s1 s2 && (s1 /= s2)
158+
159+
-- | The set of elements which are in both the first and second set
160+
intersection :: forall a. Ord a => Set a -> Set a -> Set a
161+
intersection s1 s2 = fromFoldable (ST.run (emptySTArray >>= intersect >>= unsafeFreeze))
162+
where
163+
toArray = Array.fromFoldable <<< toList
164+
ls = toArray s1
165+
rs = toArray s2
166+
ll = Array.length ls
167+
rl = Array.length rs
168+
intersect :: forall r. STArray r a -> ST r (STArray r a)
169+
intersect acc = tailRecM2 go 0 0
170+
where
171+
go = unsafePartial \l r ->
172+
if l < ll && r < rl
173+
then case compare (ls `Array.unsafeIndex` l) (rs `Array.unsafeIndex` r) of
174+
EQ -> do
175+
_ <- pushSTArray acc (ls `Array.unsafeIndex` l)
176+
pure $ Loop {a: l + 1, b: r + 1}
177+
LT -> pure $ Loop {a: l + 1, b: r}
178+
GT -> pure $ Loop {a: l, b: r + 1}
179+
else pure $ Done acc

src/Data/StrMap.js

Lines changed: 0 additions & 125 deletions
This file was deleted.

0 commit comments

Comments
 (0)