diff options
author | Mikolaj Konarski <mikolaj.konarski@funktory.com> | 2025-05-10 13:16:40 +0200 |
---|---|---|
committer | Mikolaj Konarski <mikolaj.konarski@funktory.com> | 2025-05-10 13:16:40 +0200 |
commit | f8990d90b3778e564f465de5e5b3809b73fd7936 (patch) | |
tree | be5ab8c69f95d122c3f9f0201c470e8d62f86ceb | |
parent | f2e5bf334c41f354e0d7b8e071035a018f2a198a (diff) |
Implement many filtering operations
-rw-r--r-- | src/Data/Dependent/EnumMap/Strict/Internal.hs | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/src/Data/Dependent/EnumMap/Strict/Internal.hs b/src/Data/Dependent/EnumMap/Strict/Internal.hs index d2fdcb6..369cd48 100644 --- a/src/Data/Dependent/EnumMap/Strict/Internal.hs +++ b/src/Data/Dependent/EnumMap/Strict/Internal.hs @@ -407,7 +407,10 @@ elems (DEnumMap m) = map (\(KV _ v) -> Some v) (IM.elems m) keys :: Enum1 k => DEnumMap k v -> [Some k] keys (DEnumMap m) = map (\(k, KV inf _) -> toEnum1 k inf) (IM.assocs m) --- assocs +assocs :: Enum1 k => DEnumMap k v -> [DSum k v] +assocs (DEnumMap m) = map kVToDSum $ IM.assocs m + +-- TODO: probably doesn't make much sense until we have DEnumSet? -- keysSet -- ** Lists @@ -426,7 +429,15 @@ toDescList (DEnumMap m) = map kVToDSum (IM.toDescList m) -- * Filter -- filter --- filterWithKey + +filter :: (forall a. v a -> Bool) -> DEnumMap k v -> DEnumMap k v +filter f (DEnumMap m) = DEnumMap (IM.filter (\(KV _ v) -> f v) m) + +filterWithKey :: Enum1 k => (forall a. k a -> v a -> Bool) -> DEnumMap k v -> DEnumMap k v +filterWithKey f (DEnumMap m) = + DEnumMap (IM.filterWithKey (\i (KV inf v) -> case toEnum1 i inf of Some k -> f k (coe1 v)) m) + +-- TODO: these use IntSet. Do we use a list instead of wait for DEnumSet? -- restrictKeys -- withoutKeys @@ -438,18 +449,37 @@ partitionWithKey :: Enum1 k => (forall a. k a -> v a -> Bool) -> DEnumMap k v -> partitionWithKey f (DEnumMap m) = bimap DEnumMap DEnumMap (IM.partitionWithKey (\i (KV inf v) -> case toEnum1 i inf of Some k -> f k (coe1 v)) m) --- takeWhileAntitone --- dropWhileAntitone --- spanAntitone +-- To make this more efficient, we'd need to define takeWhileAntitoneWithValue +-- for IntMap and use it here. +takeWhileAntitone :: Enum1 k => (forall a. k a -> Bool) -> DEnumMap k v -> DEnumMap k v +takeWhileAntitone f (DEnumMap m) = + DEnumMap (IM.takeWhileAntitone (\i -> case m IM.! i of KV inf _ -> case toEnum1 i inf of Some k -> f k) m) + +dropWhileAntitone :: Enum1 k => (forall a. k a -> Bool) -> DEnumMap k v -> DEnumMap k v +dropWhileAntitone f (DEnumMap m) = + DEnumMap (IM.dropWhileAntitone (\i -> case m IM.! i of KV inf _ -> case toEnum1 i inf of Some k -> f k) m) + +spanAntitone :: Enum1 k => (forall a. k a -> Bool) -> DEnumMap k v -> (DEnumMap k v, DEnumMap k v) +spanAntitone f (DEnumMap m) = + bimap DEnumMap DEnumMap (IM.spanAntitone (\i -> case m IM.! i of KV inf _ -> case toEnum1 i inf of Some k -> f k) m) -- mapMaybe -- mapMaybeWithKey -- mapEither -- mapEitherWithKey --- split --- splitLookup --- splitRoot +split :: Enum1 k => k a -> DEnumMap k v -> (DEnumMap k v, DEnumMap k v) +split k (DEnumMap m) = bimap DEnumMap DEnumMap (IM.split (fst $ fromEnum1 k) m) + +-- TODO: is this coe1 fine or can we readably check that IM doesn't cheat +-- and give us a value with a wrong type? +splitLookup :: Enum1 k => k a -> DEnumMap k v -> (DEnumMap k v, Maybe (v a), DEnumMap k v) +splitLookup k (DEnumMap m) = + let (m1, mkv, m2) = IM.splitLookup (fst $ fromEnum1 k) m + in (DEnumMap m1, (\(KV _ v) -> coe1 v) <$> mkv, DEnumMap m2) + +splitRoot :: DEnumMap k v -> [DEnumMap k v] +splitRoot (DEnumMap m) = DEnumMap <$> IM.splitRoot m -- * Submap |