1
1
{-# LANGUAGE BangPatterns, CPP, DeriveDataTypeable, MagicHash #-}
2
2
{-# LANGUAGE ScopedTypeVariables #-}
3
+ {-# LANGUAGE PatternGuards #-}
3
4
#if __GLASGOW_HASKELL__ >= 708
4
5
{-# LANGUAGE TypeFamilies #-}
5
6
#endif
@@ -52,6 +53,8 @@ module Data.HashMap.Base
52
53
, foldrWithKey
53
54
54
55
-- * Filter
56
+ , mapMaybe
57
+ , mapMaybeWithKey
55
58
, filter
56
59
, filterWithKey
57
60
@@ -81,6 +84,7 @@ module Data.HashMap.Base
81
84
, update16M
82
85
, update16With'
83
86
, updateOrConcatWith
87
+ , filterMapAux
84
88
) where
85
89
86
90
#if __GLASGOW_HASKELL__ >= 709
@@ -855,14 +859,47 @@ trim mary n = do
855
859
A. unsafeFreeze mary2
856
860
{-# INLINE trim #-}
857
861
862
+ -- | /O(n)/ Transform this map by applying a function to every value
863
+ -- and retaining only some of them.
864
+ mapMaybeWithKey :: (k -> v1 -> Maybe v2 ) -> HashMap k v1 -> HashMap k v2
865
+ mapMaybeWithKey f = filterMapAux onLeaf onColl
866
+ where onLeaf (Leaf h (L k v)) | Just v' <- f k v = Just (Leaf h (L k v'))
867
+ onLeaf _ = Nothing
868
+
869
+ onColl (L k v) | Just v' <- f k v = Just (L k v')
870
+ | otherwise = Nothing
871
+ {-# INLINE mapMaybeWithKey #-}
872
+
873
+ -- | /O(n)/ Transform this map by applying a function to every value
874
+ -- and retaining only some of them.
875
+ mapMaybe :: (v1 -> Maybe v2 ) -> HashMap k v1 -> HashMap k v2
876
+ mapMaybe f = mapMaybeWithKey (const f)
877
+ {-# INLINE mapMaybe #-}
878
+
858
879
-- | /O(n)/ Filter this map by retaining only elements satisfying a
859
880
-- predicate.
860
881
filterWithKey :: forall k v . (k -> v -> Bool ) -> HashMap k v -> HashMap k v
861
- filterWithKey pred = go
882
+ filterWithKey pred = filterMapAux onLeaf onColl
883
+ where onLeaf t@ (Leaf _ (L k v)) | pred k v = Just t
884
+ onLeaf _ = Nothing
885
+
886
+ onColl el@ (L k v) | pred k v = Just el
887
+ onColl _ = Nothing
888
+ {-# INLINE filterWithKey #-}
889
+
890
+
891
+ -- | Common implementation for 'filterWithKey' and 'mapMaybeWithKey',
892
+ -- allowing the former to former to reuse terms.
893
+ filterMapAux :: forall k v1 v2
894
+ . (HashMap k v1 -> Maybe (HashMap k v2 ))
895
+ -> (Leaf k v1 -> Maybe (Leaf k v2 ))
896
+ -> HashMap k v1
897
+ -> HashMap k v2
898
+ filterMapAux onLeaf onColl = go
862
899
where
863
900
go Empty = Empty
864
- go t@ ( Leaf _ ( L k v))
865
- | pred k v = t
901
+ go t@ Leaf {}
902
+ | Just t' <- onLeaf t = t'
866
903
| otherwise = Empty
867
904
go (BitmapIndexed b ary) = filterA ary b
868
905
go (Full ary) = filterA ary fullNodeMask
@@ -874,9 +911,9 @@ filterWithKey pred = go
874
911
mary <- A. new_ n
875
912
step ary0 mary b0 0 0 1 n
876
913
where
877
- step :: A. Array (HashMap k v ) -> A. MArray s (HashMap k v )
914
+ step :: A. Array (HashMap k v1 ) -> A. MArray s (HashMap k v2 )
878
915
-> Bitmap -> Int -> Int -> Bitmap -> Int
879
- -> ST s (HashMap k v )
916
+ -> ST s (HashMap k v2 )
880
917
step ! ary ! mary ! b i ! j ! bi n
881
918
| i >= n = case j of
882
919
0 -> return Empty
@@ -903,9 +940,9 @@ filterWithKey pred = go
903
940
mary <- A. new_ n
904
941
step ary0 mary 0 0 n
905
942
where
906
- step :: A. Array (Leaf k v ) -> A. MArray s (Leaf k v )
943
+ step :: A. Array (Leaf k v1 ) -> A. MArray s (Leaf k v2 )
907
944
-> Int -> Int -> Int
908
- -> ST s (HashMap k v )
945
+ -> ST s (HashMap k v2 )
909
946
step ! ary ! mary i ! j n
910
947
| i >= n = case j of
911
948
0 -> return Empty
@@ -915,10 +952,10 @@ filterWithKey pred = go
915
952
return $! Collision h ary2
916
953
| otherwise -> do ary2 <- trim mary j
917
954
return $! Collision h ary2
918
- | pred k v = A. write mary j el >> step ary mary (i+ 1 ) (j+ 1 ) n
955
+ | Just el <- onColl (A. index ary i)
956
+ = A. write mary j el >> step ary mary (i+ 1 ) (j+ 1 ) n
919
957
| otherwise = step ary mary (i+ 1 ) j n
920
- where el@ (L k v) = A. index ary i
921
- {-# INLINE filterWithKey #-}
958
+ {-# INLINE filterMapAux #-}
922
959
923
960
-- | /O(n)/ Filter this map by retaining only elements which values
924
961
-- satisfy a predicate.
0 commit comments