on master help sign in
Add maximumBy and minimumBy.
3186bd2Pranay Sashank
benchmark/Linear.hs+2
@@ -119,7 +119,9 @@ main =
119 , benchIOSink "findIndex" Ops.findIndex
119 , benchIOSink "findIndex" Ops.findIndex
120 , benchIOSink "elemIndex" Ops.elemIndex
120 , benchIOSink "elemIndex" Ops.elemIndex
121 , benchIOSink "maximum" Ops.maximum
121 , benchIOSink "maximum" Ops.maximum
122+ , benchIOSink "maximumBy" Ops.maximumBy
122 , benchIOSink "minimum" Ops.minimum
123 , benchIOSink "minimum" Ops.minimum
124+ , benchIOSink "minimumBy" Ops.minimumBy
123 , benchIOSink "sum" Ops.sum
125 , benchIOSink "sum" Ops.sum
124 , benchIOSink "product" Ops.product
126 , benchIOSink "product" Ops.product
125 ]
127 ]
benchmark/LinearOps.hs+7−1
@@ -17,7 +17,7 @@ import Data.Maybe (fromJust)
17import Prelude
17import Prelude
18 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (<=),
18 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (<=),
19 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
19 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
20− maxBound, div, IO)
20+ maxBound, div, IO, compare)
21import qualified Prelude as P
21import qualified Prelude as P
22import qualified Data.Foldable as F
22import qualified Data.Foldable as F
23import qualified GHC.Exts as GHC
23import qualified GHC.Exts as GHC
@@ -146,6 +146,10 @@ toList, foldr, foldrM :: Monad m => Stream m Int -> m [Int]
146last, minimum, maximum, find, findIndex, elemIndex, foldl1', foldr1
146last, minimum, maximum, find, findIndex, elemIndex, foldl1', foldr1
147 :: Monad m => Stream m Int -> m (Maybe Int)
147 :: Monad m => Stream m Int -> m (Maybe Int)
148
148
149+{-# INLINE minimumBy #-}
150+{-# INLINE maximumBy #-}
151+minimumBy, maximumBy :: Monad m => Stream m Int -> m (Maybe Int)
152+
149{-# INLINE foldl' #-}
153{-# INLINE foldl' #-}
150{-# INLINE length #-}
154{-# INLINE length #-}
151{-# INLINE sum #-}
155{-# INLINE sum #-}
@@ -213,6 +217,8 @@ maximum = S.maximum
213minimum = S.minimum
217minimum = S.minimum
214sum = S.sum
218sum = S.sum
215product = S.product
219product = S.product
220+minimumBy = S.minimumBy compare
221+maximumBy = S.maximumBy compare
216
222
217-------------------------------------------------------------------------------
223-------------------------------------------------------------------------------
218-- Transformation
224-- Transformation
src/Streamly/Prelude.hs+14−1
@@ -144,7 +144,9 @@ module Streamly.Prelude
144 -- Full folds - need to go through all elements
144 -- Full folds - need to go through all elements
145 , length
145 , length
146 , maximum
146 , maximum
147+ , maximumBy
147 , minimum
148 , minimum
149+ , minimumBy
148 , sum
150 , sum
149 , product
151 , product
150
152
@@ -706,13 +708,24 @@ product = foldl' (*) 1
706minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
708minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
707minimum m = S.minimum (toStreamS m)
709minimum m = S.minimum (toStreamS m)
708
710
711+-- | Non-overloaded version of minimum.
712+--
713+{-# INLINE minimumBy #-}
714+minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
715+minimumBy cmp m = S.minimumBy cmp (toStreamS m)
716+
709-- | Determine the maximum element in a stream.
717-- | Determine the maximum element in a stream.
710--
718--
711−-- @since 0.1.0
712{-# INLINE maximum #-}
719{-# INLINE maximum #-}
713maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
720maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
714maximum m = S.maximum (toStreamS m)
721maximum m = S.maximum (toStreamS m)
715
722
723+-- | Non-overloaded version of maximum.
724+--
725+{-# INLINE maximumBy #-}
726+maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
727+maximumBy cmp m = S.maximumBy cmp (toStreamS m)
728+
716-- | Looks the element at the given index.
729-- | Looks the element at the given index.
717--
730--
718{-# INLINE (!!) #-}
731{-# INLINE (!!) #-}
src/Streamly/Streams/StreamD.hs+40
@@ -82,7 +82,9 @@ module Streamly.Streams.StreamD
82 , all
82 , all
83 , any
83 , any
84 , maximum
84 , maximum
85+ , maximumBy
85 , minimum
86 , minimum
87+ , minimumBy
86 , findIndices
88 , findIndices
87 , lookup
89 , lookup
88 , find
90 , find
@@ -465,6 +467,25 @@ maximum (Stream step state) = go Nothing state
465 Skip s -> go (Just acc) s
467 Skip s -> go (Just acc) s
466 Stop -> return (Just acc)
468 Stop -> return (Just acc)
467
469
470+{-# INLINE_NORMAL maximumBy #-}
471+maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
472+maximumBy cmp (Stream step state) = go Nothing state
473+ where
474+ go Nothing st = do
475+ r <- step defState st
476+ case r of
477+ Yield x s -> go (Just x) s
478+ Skip s -> go Nothing s
479+ Stop -> return Nothing
480+ go (Just acc) st = do
481+ r <- step defState st
482+ case r of
483+ Yield x s -> case cmp acc x of
484+ GT -> go (Just acc) s
485+ _ -> go (Just x) s
486+ Skip s -> go (Just acc) s
487+ Stop -> return (Just acc)
488+
468{-# INLINE_NORMAL minimum #-}
489{-# INLINE_NORMAL minimum #-}
469minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
490minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
470minimum (Stream step state) = go Nothing state
491minimum (Stream step state) = go Nothing state
@@ -484,6 +505,25 @@ minimum (Stream step state) = go Nothing state
484 Skip s -> go (Just acc) s
505 Skip s -> go (Just acc) s
485 Stop -> return (Just acc)
506 Stop -> return (Just acc)
486
507
508+{-# INLINE_NORMAL minimumBy #-}
509+minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
510+minimumBy cmp (Stream step state) = go Nothing state
511+ where
512+ go Nothing st = do
513+ r <- step defState st
514+ case r of
515+ Yield x s -> go (Just x) s
516+ Skip s -> go Nothing s
517+ Stop -> return Nothing
518+ go (Just acc) st = do
519+ r <- step defState st
520+ case r of
521+ Yield x s -> case cmp acc x of
522+ GT -> go (Just x) s
523+ _ -> go (Just acc) s
524+ Skip s -> go (Just acc) s
525+ Stop -> return (Just acc)
526+
487{-# INLINE_NORMAL (!!) #-}
527{-# INLINE_NORMAL (!!) #-}
488(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
528(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
489(Stream step state) !! i = go i state
529(Stream step state) !! i = go i state
src/Streamly/Streams/StreamK.hs+42
@@ -90,7 +90,9 @@ module Streamly.Streams.StreamK
90 , any
90 , any
91 , last
91 , last
92 , minimum
92 , minimum
93+ , minimumBy
93 , maximum
94 , maximum
95+ , maximumBy
94 , findIndices
96 , findIndices
95 , lookup
97 , lookup
96 , find
98 , find
@@ -712,6 +714,26 @@ minimum m = go Nothing (toStream m)
712 else go (Just a) r
714 else go (Just a) r
713 in unStream m1 defState stop single yieldk
715 in unStream m1 defState stop single yieldk
714
716
717+{-# INLINE minimumBy #-}
718+minimumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
719+minimumBy cmp m = go Nothing (toStream m)
720+ where
721+ go Nothing m1 =
722+ let stop = return Nothing
723+ single a = return (Just a)
724+ yieldk a r = go (Just a) r
725+ in unStream m1 defState stop single yieldk
726+
727+ go (Just res) m1 =
728+ let stop = return (Just res)
729+ single a = case cmp res a of
730+ GT -> return (Just a)
731+ _ -> return (Just res)
732+ yieldk a r = case cmp res a of
733+ GT -> go (Just a) r
734+ _ -> go (Just res) r
735+ in unStream m1 defState stop single yieldk
736+
715{-# INLINE maximum #-}
737{-# INLINE maximum #-}
716maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
738maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
717maximum m = go Nothing (toStream m)
739maximum m = go Nothing (toStream m)
@@ -734,6 +756,26 @@ maximum m = go Nothing (toStream m)
734 else go (Just res) r
756 else go (Just res) r
735 in unStream m1 defState stop single yieldk
757 in unStream m1 defState stop single yieldk
736
758
759+{-# INLINE maximumBy #-}
760+maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
761+maximumBy cmp m = go Nothing (toStream m)
762+ where
763+ go Nothing m1 =
764+ let stop = return Nothing
765+ single a = return (Just a)
766+ yieldk a r = go (Just a) r
767+ in unStream m1 defState stop single yieldk
768+
769+ go (Just res) m1 =
770+ let stop = return (Just res)
771+ single a = case cmp res a of
772+ GT -> return (Just res)
773+ _ -> return (Just a)
774+ yieldk a r = case cmp res a of
775+ GT -> go (Just res) r
776+ _ -> go (Just a) r
777+ in unStream m1 defState stop single yieldk
778+
737{-# INLINE (!!) #-}
779{-# INLINE (!!) #-}
738(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
780(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
739m !! i = go i (toStream m)
781m !! i = go i (toStream m)
test/Prop.hs+13−1
@@ -13,7 +13,8 @@ import Data.Function ((&))
13import Data.IORef (readIORef, modifyIORef, newIORef)
13import Data.IORef (readIORef, modifyIORef, newIORef)
14import Data.List
14import Data.List
15 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
15 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
16− elemIndex, find, insertBy, intersperse, foldl1', (\\))
16+ elemIndex, find, insertBy, intersperse, foldl1', (\\),
17+ maximumBy, minimumBy)
17import Data.Maybe (mapMaybe)
18import Data.Maybe (mapMaybe)
18import GHC.Word (Word8)
19import GHC.Word (Word8)
19
20
@@ -550,6 +551,17 @@ eliminationOps constr desc t = do
550 prop (desc <> " maximum") $ eliminateOp constr (wrapMaybe maximum) $ S.maximum . t
551 prop (desc <> " maximum") $ eliminateOp constr (wrapMaybe maximum) $ S.maximum . t
551 prop (desc <> " minimum") $ eliminateOp constr (wrapMaybe minimum) $ S.minimum . t
552 prop (desc <> " minimum") $ eliminateOp constr (wrapMaybe minimum) $ S.minimum . t
552
553
554+ prop (desc <> " maximumBy compare") $
555+ eliminateOp constr (wrapMaybe $ maximumBy compare) $ S.maximumBy compare . t
556+ prop (desc <> " maximumBy flip compare") $
557+ eliminateOp constr (wrapMaybe $ maximumBy $ flip compare) $
558+ S.maximumBy (flip compare) . t
559+ prop (desc <> " minimumBy compare") $
560+ eliminateOp constr (wrapMaybe $ minimumBy compare) $ S.minimumBy compare . t
561+ prop (desc <> " minimumBy flip compare") $
562+ eliminateOp constr (wrapMaybe $ minimumBy $ flip compare) $
563+ S.minimumBy (flip compare) . t
564+
553 prop (desc <> " findIndex") $ eliminateOp constr (findIndex odd) $ S.findIndex odd . t
565 prop (desc <> " findIndex") $ eliminateOp constr (findIndex odd) $ S.findIndex odd . t
554 prop (desc <> " elemIndex") $ eliminateOp constr (elemIndex 3) $ S.elemIndex 3 . t
566 prop (desc <> " elemIndex") $ eliminateOp constr (elemIndex 3) $ S.elemIndex 3 . t
555
567