@@ -16,6 +16,8 @@ module Data.Map
16
16
, lookupGT
17
17
, findMin
18
18
, findMax
19
+ , foldSubmap
20
+ , submap
19
21
, fromFoldable
20
22
, fromFoldableWith
21
23
, toUnfoldable
@@ -44,7 +46,7 @@ import Data.Foldable (foldl, foldMap, foldr, class Foldable)
44
46
import Data.List (List (..), (:), length , nub )
45
47
import Data.List.Lazy as LL
46
48
import Data.Maybe (Maybe (..), maybe , isJust , fromMaybe )
47
- import Data.Monoid (class Monoid )
49
+ import Data.Monoid (class Monoid , mempty )
48
50
import Data.Ord (class Ord1 )
49
51
import Data.Traversable (traverse , class Traversable )
50
52
import Data.Tuple (Tuple (Tuple), snd , uncurry )
@@ -254,6 +256,67 @@ findMin Leaf = Nothing
254
256
findMin (Two left k1 v1 _) = Just $ fromMaybe { key: k1, value: v1 } $ findMin left
255
257
findMin (Three left k1 v1 _ _ _ _) = Just $ fromMaybe { key: k1, value: v1 } $ findMin left
256
258
259
+ -- | Fold over the entries of a given map where the key is between a lower and
260
+ -- | an upper bound. Passing `Nothing` as either the lower or upper bound
261
+ -- | argument means that the fold has no lower or upper bound, i.e. the fold
262
+ -- | starts from (or ends with) the smallest (or largest) key in the map.
263
+ -- |
264
+ -- | ```purescript
265
+ -- | foldSubmap (Just 1) (Just 2) (\_ v -> [v])
266
+ -- | (fromFoldable [Tuple 0 "zero", Tuple 1 "one", Tuple 2 "two", Tuple 3 "three"])
267
+ -- | == ["one", "two"]
268
+ -- |
269
+ -- | foldSubmap Nothing (Just 2) (\_ v -> [v])
270
+ -- | (fromFoldable [Tuple 0 "zero", Tuple 1 "one", Tuple 2 "two", Tuple 3 "three"])
271
+ -- | == ["zero", "one", "two"]
272
+ -- | ```
273
+ foldSubmap :: forall k v m . Ord k => Monoid m => Maybe k -> Maybe k -> (k -> v -> m ) -> Map k v -> m
274
+ foldSubmap kmin kmax f =
275
+ let
276
+ geqMin = case kmin of
277
+ Just kmin' ->
278
+ \x -> x >= kmin'
279
+ Nothing ->
280
+ const true
281
+ leqMax = case kmax of
282
+ Just kmax' ->
283
+ \x -> x <= kmax'
284
+ Nothing ->
285
+ const true
286
+
287
+ go = case _ of
288
+ Leaf ->
289
+ mempty
290
+ Two left k v right ->
291
+ (if geqMin k then go left else mempty)
292
+ <> (if geqMin k && leqMax k then f k v else mempty)
293
+ <> (if leqMax k then go right else mempty)
294
+ Three left k1 v1 mid k2 v2 right ->
295
+ (if geqMin k1 then go left else mempty)
296
+ <> (if geqMin k1 && leqMax k1 then f k1 v1 else mempty)
297
+ <> (if geqMin k1 && leqMax k2 then go mid else mempty)
298
+ <> (if geqMin k2 && leqMax k2 then f k2 v2 else mempty)
299
+ <> (if leqMax k2 then go right else mempty)
300
+ in
301
+ go
302
+
303
+ -- | Returns a new map containing all entries of the argument map which lie
304
+ -- | between a given lower and upper bound, treating `Nothing` as no bound i.e.
305
+ -- | including the smallest (or largest) key in the map, no matter how small
306
+ -- | (or large) it is. The function is entirely specified by the following
307
+ -- | property:
308
+ -- |
309
+ -- | ```purescript
310
+ -- | forall m :: Map k v, mmin :: Maybe k, mmax :: Maybe k, key :: k,
311
+ -- | let m' = submap mmin mmax m in
312
+ -- | if (maybe true (\min -> min <= key) mmin &&
313
+ -- | maybe true (\max -> max >= key) mmax)
314
+ -- | then lookup key m == lookup key m'
315
+ -- | else not (member key m')
316
+ -- | ```
317
+ submap :: forall k v . Ord k => Maybe k -> Maybe k -> Map k v -> Map k v
318
+ submap kmin kmax = foldSubmap kmin kmax singleton
319
+
257
320
-- | Test if a key is a member of a map
258
321
member :: forall k v . Ord k => k -> Map k v -> Boolean
259
322
member k m = isJust (k `lookup` m)
0 commit comments