Commits

Bryan O'Sullivan committed 17ec386

Implement and test lazy findIndex and findIndices

Comments (0)

Files changed (5)

Data/Text/Fusion.hs

 -- returns the index of the first element in the stream
 -- satisfying the predicate.
 findIndex :: (Char -> Bool) -> Stream Char -> Maybe Int
-findIndex p s = case findIndices p s of
-                  (i:_) -> Just i
-                  _     -> Nothing
+findIndex = S.findIndexI
 {-# INLINE [0] findIndex #-}
 
 -- | The 'findIndices' function takes a predicate and a stream and
 -- returns all indices of the elements in the stream
 -- satisfying the predicate.
 findIndices :: (Char -> Bool) -> Stream Char -> [Int]
-findIndices p (Stream next s0 _len) = loop_findIndex 0 s0
-  where
-    loop_findIndex !i !s = case next s of
-      Done                   -> []
-      Skip    s'             -> loop_findIndex i     s' -- hmm. not caught by QC
-      Yield x s' | p x       -> i : loop_findIndex (i+1) s'
-                 | otherwise -> loop_findIndex (i+1) s'
+findIndices = S.findIndicesI
 {-# INLINE [0] findIndices #-}
 
 -- | The 'findIndexOrEnd' function takes a predicate and a stream and

Data/Text/Fusion/Common.hs

     -- * Indexing
     , find
     , indexI
+    , findIndexI
+    , findIndicesI
 
     -- * Zipping and unzipping
     , zipWith
   filter p (filter q s) = filter (\x -> q x && p x) s
   #-}
 
+-- | The 'findIndexI' function takes a predicate and a stream and
+-- returns the index of the first element in the stream satisfying the
+-- predicate.
+findIndexI :: Integral a => (Char -> Bool) -> Stream Char -> Maybe a
+findIndexI p s = case findIndicesI p s of
+                  (i:_) -> Just i
+                  _     -> Nothing
+{-# INLINE [0] findIndexI #-}
+
+-- | The 'findIndicesI' function takes a predicate and a stream and
+-- returns all indices of the elements in the stream satisfying the
+-- predicate.
+findIndicesI :: Integral a => (Char -> Bool) -> Stream Char -> [a]
+findIndicesI p (Stream next s0 _len) = loop_findIndex 0 s0
+  where
+    loop_findIndex !i !s = case next s of
+      Done                   -> []
+      Skip    s'             -> loop_findIndex i     s' -- hmm. not caught by QC
+      Yield x s' | p x       -> i : loop_findIndex (i+1) s'
+                 | otherwise -> loop_findIndex (i+1) s'
+{-# INLINE [0] findIndicesI #-}
+
 -------------------------------------------------------------------------------
 -- * Zipping
 

Data/Text/Lazy.hs

     
     -- * Indexing
     , index
-    -- , findIndex
-    -- , findIndices
+    , findIndex
+    , findIndices
     -- , elemIndex
     -- , elemIndices
     -- , count
 index t n = S.index (stream t) n
 {-# INLINE index #-}
 
+-- | /O(n)/ The 'findIndex' function takes a predicate and a 'Text'
+-- and returns the index of the first element in the 'Text' satisfying
+-- the predicate. This function is subject to fusion.
+findIndex :: (Char -> Bool) -> Text -> Maybe Int64
+findIndex p t = S.findIndex p (stream t)
+{-# INLINE findIndex #-}
+
+-- | The 'findIndices' function extends 'findIndex', by returning the
+-- indices of all elements satisfying the predicate, in ascending
+-- order. This function is subject to fusion.
+findIndices :: (Char -> Bool) -> Text -> [Int64]
+findIndices p t = S.findIndices p (stream t)
+{-# INLINE findIndices #-}
+
 -- | /O(n)/ 'zipWith' generalises 'zip' by zipping with the function
 -- given as the first argument, instead of a tupling function.
 zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text

Data/Text/Lazy/Fusion.hs

     , length
     , unfoldrN
     , index
+    , findIndex
+    , findIndices
     ) where
 
 import Prelude hiding (length)
 index :: Stream Char -> Int64 -> Char
 index = S.indexI
 {-# INLINE [0] index #-}
+
+-- | The 'findIndex' function takes a predicate and a stream and
+-- returns the index of the first element in the stream
+-- satisfying the predicate.
+findIndex :: (Char -> Bool) -> Stream Char -> Maybe Int64
+findIndex = S.findIndexI
+{-# INLINE [0] findIndex #-}
+
+-- | The 'findIndices' function takes a predicate and a stream and
+-- returns all indices of the elements in the stream
+-- satisfying the predicate.
+findIndices :: (Char -> Bool) -> Stream Char -> [Int64]
+findIndices = S.findIndicesI
+{-# INLINE [0] findIndices #-}

tests/Properties.hs

 
 prop_T_index x s       = x < L.length s && x >= 0 ==>
                          (L.!!) s x == T.index (packT s) x
+prop_TL_index x s      = x < L.length s && x >= 0 ==>
+                         (L.!!) s x == TL.index (packT s) (fromIntegral x)
 prop_T_findIndex p     = L.findIndex p `eqP` T.findIndex p
-prop_T_findIndices p   = L.findIndices p`eqP` T.findIndices p
+prop_TL_findIndex p    = (fmap fromIntegral . L.findIndex p) `eqP` TL.findIndex p
+prop_T_findIndices p   = L.findIndices p `eqP` T.findIndices p
+prop_TL_findIndices p  = (fmap fromIntegral . L.findIndices p) `eqP` TL.findIndices p
 prop_T_elemIndex c     = L.elemIndex c `eqP` T.elemIndex c
 prop_T_elemIndices c   = L.elemIndices c`eqP` T.elemIndices c
 prop_T_count c         = (L.length . L.elemIndices c) `eqP` T.count c
 
   ("prop_T_index", mytest prop_T_index),
   ("prop_T_findIndex", mytest prop_T_findIndex),
+  ("prop_TL_findIndex", mytest prop_TL_findIndex),
   ("prop_T_findIndices", mytest prop_T_findIndices),
+  ("prop_TL_findIndices", mytest prop_TL_findIndices),
   ("prop_T_elemIndex", mytest prop_T_elemIndex),
   ("prop_T_elemIndices", mytest prop_T_elemIndices),
   ("prop_T_count", mytest prop_T_count),