on master help sign in
add mapMaybe combinator in Fold

Add benchmarking and test case for mapMaybe combinator of Data.Fold Fix review comments

commit60d13da0d65b7f193b22050d6efacba44b478096 authorRanjeet Ranjan <ranjeetr@composewell.com> dateSat 17 Oct 2020, 15:06 (6 years ago) parent9444e3e
3 files changed+23−1
benchmark/Streamly/Benchmark/Data/Fold.hs+7 src/Streamly/Internal/Data/Fold.hs+12−1 test/Streamly/Test/Data/Fold.hs+4
benchmark/Streamly/Benchmark/Data/Fold.hs+7
@@ -159,6 +159,13 @@ o_1_space_serial_transformation value =
159159 [ bgroup "serially"
160160 [ bgroup "transformation"
161161 [ benchIOSink value "lmap" (S.fold (IFL.lmap (+ 1) FL.drain))
162+ , benchIOSink
163+ value
164+ "mapMaybe"
165+ (S.fold
166+ (IFL.mapMaybe
167+ (\x -> case x of 1 -> Just x ; _ -> Nothing)
168+ FL.drain))
162169 , benchIOSink
163170 value
164171 "sequence"
src/Streamly/Internal/Data/Fold.hs+12−1
@@ -102,7 +102,7 @@ module Streamly.Internal.Data.Fold
102102 -- , ldeleteBy
103103 -- , luniq
104104 , lcatMaybes
105−
105+ , mapMaybe
106106 {-
107107 -- ** Mapping Filters
108108 , lmapMaybe
@@ -208,6 +208,7 @@ import Control.Monad.IO.Class (MonadIO(..))
208208import Data.Functor.Identity (Identity(..))
209209import Data.Int (Int64)
210210import Data.Map.Strict (Map)
211+import Data.Maybe (isJust, fromJust)
211212#if __GLASGOW_HASKELL__ < 804
212213import Data.Semigroup (Semigroup((<>)))
213214#endif
@@ -314,6 +315,16 @@ sequence (Fold step initial extract) = Fold step initial extract'
314315mapM :: Monad m => (b -> m c) -> Fold m a b -> Fold m a c
315316mapM f = sequence . fmap f
316317
318+-- | @(mapMaybe f fold)@ maps a 'Maybe' returning function @f@ on the input of the fold,
319+-- filter out the 'Nothing' elements, and return a values extracted from 'Just'.
320+-- >>> S.fold (FL.mapMaybe (\x -> case x of 5 -> Just x ; _ -> Nothing) FL.sum)
321+-- (S.enumerateFromTo 1 10)
322+-- 5
323+-- /Internal/
324+{-# INLINE mapMaybe #-}
325+mapMaybe :: (Monad m) => (a -> Maybe b) -> Fold m b r -> Fold m a r
326+mapMaybe f = lmap f . lfilter isJust . lmap fromJust
327+
317328------------------------------------------------------------------------------
318329-- Transformations on fold inputs
319330------------------------------------------------------------------------------
test/Streamly/Test/Data/Fold.hs+4
@@ -96,6 +96,9 @@ safeLast (_:xs) = safeLast xs
9696last :: [String] -> Expectation
9797last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
9898
99+mapMaybe :: [Int] -> Expectation
100+mapMaybe ls = S.fold (F.mapMaybe (\x -> if even x then Just x else Nothing) FL.toList)
101+ (S.fromList ls) `shouldReturn` filter even ls
99102
100103nth :: Int -> [a] -> Maybe a
101104nth idx (x:xs) = if idx == 0
@@ -213,3 +216,4 @@ main = hspec $
213216 prop "Any" $ Main.any predicate
214217 prop "And" Main.and
215218 prop "Or" Main.or
219+ prop "mapMaybe" mapMaybe