Skip to content

Commit 3907933

Browse files
authored
Add any & anyWithKey (#73)
1 parent 313ec0c commit 3907933

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Notable changes to this project are documented in this file. The format is based
77
Breaking changes:
88

99
New features:
10+
* Add `Data.Map.any` (#73 by @flip111)
11+
* Add `Data.Map.anyWithKey` (#73 by @flip111)
1012

1113
Bugfixes:
1214

src/Data/Map.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Data.Eq (class Eq1)
1212
import Data.Foldable (class Foldable)
1313
import Data.FoldableWithIndex (class FoldableWithIndex)
1414
import Data.FunctorWithIndex (class FunctorWithIndex)
15-
import Data.Map.Internal (Map, alter, catMaybes, checkValid, delete, empty, filter, filterKeys, filterWithKey, findMax, findMin, foldSubmap, fromFoldable, fromFoldableWith, fromFoldableWithIndex, insert, insertWith, isEmpty, isSubmap, lookup, lookupGE, lookupGT, lookupLE, lookupLT, member, pop, showTree, singleton, size, submap, toUnfoldable, toUnfoldableUnordered, union, unionWith, unions, intersection, intersectionWith, difference, update, values, mapMaybeWithKey, mapMaybe)
15+
import Data.Map.Internal (Map, alter, catMaybes, checkValid, delete, empty, filter, filterKeys, filterWithKey, findMax, findMin, foldSubmap, fromFoldable, fromFoldableWith, fromFoldableWithIndex, insert, insertWith, isEmpty, isSubmap, lookup, lookupGE, lookupGT, lookupLE, lookupLT, member, pop, showTree, singleton, size, submap, toUnfoldable, toUnfoldableUnordered, union, unionWith, unions, intersection, intersectionWith, difference, update, values, mapMaybeWithKey, mapMaybe, any, anyWithKey)
1616
import Data.Newtype (class Newtype)
1717
import Data.Ord (class Ord1)
1818
import Data.Traversable (class Traversable)

src/Data/Map/Internal.purs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ module Data.Map.Internal
4646
, mapMaybeWithKey
4747
, mapMaybe
4848
, catMaybes
49+
, any
50+
, anyWithKey
4951
, MapIter
5052
, MapIterStep(..)
5153
, toMapIter
@@ -672,6 +674,26 @@ mapMaybe = mapMaybeWithKey <<< const
672674
catMaybes :: forall k v. Ord k => Map k (Maybe v) -> Map k v
673675
catMaybes = mapMaybe identity
674676

677+
-- | Returns true if at least one map element satisfies the given predicateon the value,
678+
-- | iterating the map only as necessary and stopping as soon as the predicate
679+
-- | yields true.
680+
any :: forall k v. (v -> Boolean) -> Map k v -> Boolean
681+
any predicate = go
682+
where
683+
go = case _ of
684+
Leaf -> false
685+
Node _ _ _ mv ml mr -> predicate mv || go ml || go mr
686+
687+
-- | Returns true if at least one map element satisfies the given predicate,
688+
-- | iterating the map only as necessary and stopping as soon as the predicate
689+
-- | yields true.
690+
anyWithKey :: forall k v. (k -> v -> Boolean) -> Map k v -> Boolean
691+
anyWithKey predicate = go
692+
where
693+
go = case _ of
694+
Leaf -> false
695+
Node _ _ mk mv ml mr -> predicate mk mv || go ml || go mr
696+
675697
-- | Low-level Node constructor which maintains the height and size invariants
676698
-- | This is unsafe because it assumes the child Maps are ordered and balanced.
677699
unsafeNode :: forall k v. Fn4 k v (Map k v) (Map k v) (Map k v)

test/Test/Data/Map.purs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ import Data.Foldable (foldl, for_, all, and)
99
import Data.FoldableWithIndex (foldrWithIndex)
1010
import Data.Function (on)
1111
import Data.FunctorWithIndex (mapWithIndex)
12-
import Data.List (List(..), groupBy, length, nubBy, singleton, sort, sortBy, (:))
12+
import Data.List (List(..), groupBy, length, nubBy, singleton, sort, sortBy, (:), head, last)
1313
import Data.List.NonEmpty as NEL
1414
import Data.Map as M
1515
import Data.Map.Gen (genMap)
1616
import Data.Maybe (Maybe(..), fromMaybe, maybe)
1717
import Data.Semigroup.First (First(..))
1818
import Data.Semigroup.Last (Last(..))
19-
import Data.Tuple (Tuple(..), fst, uncurry)
19+
import Data.Tuple (Tuple(..), fst, snd, uncurry)
2020
import Effect (Effect)
2121
import Effect.Console (log)
22+
import Effect.Exception (throwException, error)
2223
import Partial.Unsafe (unsafePartial)
2324
import Test.QuickCheck ((<?>), (<=?), (===), quickCheck, quickCheck')
2425
import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary)
@@ -448,5 +449,30 @@ mapTests = do
448449
let result = left <> right
449450
result == right
450451

452+
log "any"
453+
quickCheck $ \(TestMap m :: TestMap SmallKey Int) ->
454+
let list = M.toUnfoldable m
455+
in case head list of
456+
Nothing -> true
457+
Just h -> case last list of
458+
Nothing -> true
459+
Just l -> M.any (\x -> x == snd h) m && M.any (\x -> x == snd l) m
460+
461+
log "any with empty map"
462+
when (M.any (\_ -> true) (M.empty :: M.Map SmallKey Int)) $ throwException $ error "Test any with empty map failed"
463+
464+
log "anyWithKey"
465+
quickCheck $ \(TestMap m :: TestMap SmallKey Int) ->
466+
let list = M.toUnfoldable m
467+
in case head list of
468+
Nothing -> true
469+
Just h -> case last list of
470+
Nothing -> true
471+
Just l -> M.anyWithKey (\k v -> k == fst h && v == snd h) m && M.anyWithKey (\k v -> k == fst l && v == snd l) m
472+
473+
log "anyWithKey with empty map"
474+
when (M.anyWithKey (\_ _ -> true) (M.empty :: M.Map SmallKey Int)) $ throwException $ error "Test anyWithKey with empty map failed"
475+
476+
451477
smSingleton :: forall key value. key -> value -> M.SemigroupMap key value
452478
smSingleton k v = M.SemigroupMap (M.singleton k v)

0 commit comments

Comments
 (0)