on master help sign in
Add Prelude#findIndices, Prelude#findIndex, Prelude#elemIndices, Prelude#elemIndex
52eccb9Veladus
src/Streamly/Prelude.hs+29
@@ -104,6 +104,13 @@ module Streamly.Prelude
104 , sum
104 , sum
105 , product
105 , product
106
106
107+ -- *** Indices
108+ , findIndices
109+ , findIndex
110+ , elemIndices
111+ , elemIndex
112+
113+
107 -- ** Map and Fold
114 -- ** Map and Fold
108 , mapM_
115 , mapM_
109
116
@@ -593,6 +600,28 @@ minimum m = S.minimum (toStreamS m)
593maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
600maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
594maximum m = S.maximum (toStreamS m)
601maximum m = S.maximum (toStreamS m)
595
602
603+-- | Finds all the indices of elements satisfying the given predicate.
604+{-# INLINE findIndices #-}
605+findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
606+findIndices = K.findIndices
607+
608+-- | Gives the index of the first stream element satisfying the given
609+-- preficate.
610+{-# INLINE findIndex #-}
611+findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
612+findIndex p = head . findIndices p
613+
614+-- | Finds the index of all elements in the stream which are equal to the
615+-- given.
616+{-# INLINE elemIndices #-}
617+elemIndices :: (IsStream t, Eq a) => a -> t m a -> t m Int
618+elemIndices a = findIndices (==a)
619+
620+-- | Gives the first index of an element in the stream, which equals the given.
621+{-# INLINE elemIndex #-}
622+elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int)
623+elemIndex a = findIndex (==a)
624+
596------------------------------------------------------------------------------
625------------------------------------------------------------------------------
597-- Map and Fold
626-- Map and Fold
598------------------------------------------------------------------------------
627------------------------------------------------------------------------------
src/Streamly/Streams/StreamK.hs+12
@@ -89,6 +89,7 @@ module Streamly.Streams.StreamK
89 , last
89 , last
90 , minimum
90 , minimum
91 , maximum
91 , maximum
92+ , findIndices
92
93
93 -- ** Map and Fold
94 -- ** Map and Fold
94 , mapM_
95 , mapM_
@@ -674,6 +675,17 @@ maximum m = go Nothing (toStream m)
674 else go (Just res) r
675 else go (Just res) r
675 in unStream m1 defState stop single yieldk
676 in unStream m1 defState stop single yieldk
676
677
678+{-# INLINE findIndices #-}
679+findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
680+findIndices p = fromStream . go 0 . toStream
681+ where
682+ go offset m1 = Stream $ \st stp sng yld ->
683+ let single a | p a = sng offset
684+ | otherwise = stp
685+ yieldk a x | p a = yld offset $ go (offset + 1) x
686+ | otherwise = unStream (go (offset + 1) x) st stp sng yld
687+ in unStream m1 (rstState st) stp single yieldk
688+
677------------------------------------------------------------------------------
689------------------------------------------------------------------------------
678-- Map and Fold
690-- Map and Fold
679------------------------------------------------------------------------------
691------------------------------------------------------------------------------
test/Prop.hs+9−1
@@ -9,7 +9,8 @@ import Control.Applicative (ZipList(..))
9import Control.Concurrent (MVar, takeMVar, putMVar, newEmptyMVar)
9import Control.Concurrent (MVar, takeMVar, putMVar, newEmptyMVar)
10import Control.Monad (replicateM, replicateM_)
10import Control.Monad (replicateM, replicateM_)
11import Data.IORef (readIORef, modifyIORef, newIORef)
11import Data.IORef (readIORef, modifyIORef, newIORef)
12−import Data.List (sort, foldl', scanl')
12+import Data.List (sort, foldl', scanl', findIndices, findIndex, elemIndices,
13+ elemIndex)
13import Data.Maybe (mapMaybe)
14import Data.Maybe (mapMaybe)
14import GHC.Word (Word8)
15import GHC.Word (Word8)
15
16
@@ -347,6 +348,10 @@ transformOps constr desc t eq = do
347 prop (desc ++ " scan") $ transform (scanl' (+) 0) $ t . (S.scanl' (+) 0)
348 prop (desc ++ " scan") $ transform (scanl' (+) 0) $ t . (S.scanl' (+) 0)
348 prop (desc ++ " reverse") $ transform reverse $ t . S.reverse
349 prop (desc ++ " reverse") $ transform reverse $ t . S.reverse
349
350
351+ prop (desc ++ " findIndices") $ transform (findIndices odd) $ t . (S.findIndices odd)
352+ prop (desc ++ " elemIndices") $ transform (elemIndices 3) $ t . (S.elemIndices 3)
353+
354+
350concurrentOps
355concurrentOps
351 :: IsStream t
356 :: IsStream t
352 => ([Word8] -> t IO Word8)
357 => ([Word8] -> t IO Word8)
@@ -481,6 +486,9 @@ eliminationOps constr desc t = do
481 prop (desc ++ " maximum") $ eliminateOp constr (wrapMaybe maximum) $ S.maximum . t
486 prop (desc ++ " maximum") $ eliminateOp constr (wrapMaybe maximum) $ S.maximum . t
482 prop (desc ++ " minimum") $ eliminateOp constr (wrapMaybe minimum) $ S.minimum . t
487 prop (desc ++ " minimum") $ eliminateOp constr (wrapMaybe minimum) $ S.minimum . t
483
488
489+ prop (desc ++ " findIndex") $ eliminateOp constr (findIndex odd) $ (S.findIndex odd) . t
490+ prop (desc ++ " elemIndex") $ eliminateOp constr (elemIndex 3) $ (S.elemIndex 3) . t
491+
484-- head/tail/last may depend on the order in case of parallel streams
492-- head/tail/last may depend on the order in case of parallel streams
485-- so we test these only for serial streams.
493-- so we test these only for serial streams.
486serialEliminationOps
494serialEliminationOps