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
@@ -855,14 +858,46 @@ trim mary n = do
855
858
A. unsafeFreeze mary2
856
859
{-# INLINE trim #-}
857
860
861
+ -- | /O(n)/ Transform this map by applying a function to every value
862
+ -- and retaining only some of them.
863
+ mapMaybeWithKey :: (k -> v1 -> Maybe v2 ) -> HashMap k v1 -> HashMap k v2
864
+ mapMaybeWithKey f = filterMapAux onLeaf onColl
865
+ where onLeaf (Leaf h (L k v)) | Just v' <- f k v = Just (Leaf h (L k v'))
866
+ onLeaf _ = Nothing
867
+
868
+ onColl (L k v) | Just v' <- f k v = Just (L k v')
869
+ | otherwise = Nothing
870
+ {-# INLINE mapMaybeWithKey #-}
871
+
872
+ -- | /O(n)/ Transform this map by applying a function to every value
873
+ -- and retaining only some of them.
874
+ mapMaybe :: (v1 -> Maybe v2 ) -> HashMap k v1 -> HashMap k v2
875
+ mapMaybe f = mapMaybeWithKey (const f)
876
+ {-# INLINE mapMaybe #-}
877
+
858
878
-- | /O(n)/ Filter this map by retaining only elements satisfying a
859
879
-- predicate.
860
880
filterWithKey :: forall k v . (k -> v -> Bool ) -> HashMap k v -> HashMap k v
861
- filterWithKey pred = go
881
+ filterWithKey pred = filterMapAux onLeaf onColl
882
+ where onLeaf t@ (Leaf _ (L k v)) | pred k v = Just t
883
+ onLeaf _ = Nothing
884
+
885
+ onColl el@ (L k v) | pred k v = Just el
886
+ onColl _ = Nothing
887
+
888
+
889
+ -- | Common implementation for 'filterWithKey' and 'mapMaybeWithKey',
890
+ -- allowing the former to former to reuse terms.
891
+ filterMapAux :: forall k v1 v2
892
+ . (HashMap k v1 -> Maybe (HashMap k v2 ))
893
+ -> (Leaf k v1 -> Maybe (Leaf k v2 ))
894
+ -> HashMap k v1
895
+ -> HashMap k v2
896
+ filterMapAux onLeaf onColl = go
862
897
where
863
898
go Empty = Empty
864
- go t@ ( Leaf _ ( L k v))
865
- | pred k v = t
899
+ go t@ Leaf {}
900
+ | Just t' <- onLeaf t = t'
866
901
| otherwise = Empty
867
902
go (BitmapIndexed b ary) = filterA ary b
868
903
go (Full ary) = filterA ary fullNodeMask
@@ -874,9 +909,9 @@ filterWithKey pred = go
874
909
mary <- A. new_ n
875
910
step ary0 mary b0 0 0 1 n
876
911
where
877
- step :: A. Array (HashMap k v ) -> A. MArray s (HashMap k v )
912
+ step :: A. Array (HashMap k v1 ) -> A. MArray s (HashMap k v2 )
878
913
-> Bitmap -> Int -> Int -> Bitmap -> Int
879
- -> ST s (HashMap k v )
914
+ -> ST s (HashMap k v2 )
880
915
step ! ary ! mary ! b i ! j ! bi n
881
916
| i >= n = case j of
882
917
0 -> return Empty
@@ -903,9 +938,9 @@ filterWithKey pred = go
903
938
mary <- A. new_ n
904
939
step ary0 mary 0 0 n
905
940
where
906
- step :: A. Array (Leaf k v ) -> A. MArray s (Leaf k v )
941
+ step :: A. Array (Leaf k v1 ) -> A. MArray s (Leaf k v2 )
907
942
-> Int -> Int -> Int
908
- -> ST s (HashMap k v )
943
+ -> ST s (HashMap k v2 )
909
944
step ! ary ! mary i ! j n
910
945
| i >= n = case j of
911
946
0 -> return Empty
@@ -915,9 +950,9 @@ filterWithKey pred = go
915
950
return $! Collision h ary2
916
951
| otherwise -> do ary2 <- trim mary j
917
952
return $! Collision h ary2
918
- | pred k v = A. write mary j el >> step ary mary (i+ 1 ) (j+ 1 ) n
953
+ | Just el <- onColl (A. index ary i)
954
+ = A. write mary j el >> step ary mary (i+ 1 ) (j+ 1 ) n
919
955
| otherwise = step ary mary (i+ 1 ) j n
920
- where el@ (L k v) = A. index ary i
921
956
{-# INLINE filterWithKey #-}
922
957
923
958
-- | /O(n)/ Filter this map by retaining only elements which values
0 commit comments