on master help sign in
make sliceBeginWith fail when first element fails predicate
e4e1d25Anurag Hooda
benchmark/Streamly/Benchmark/Data/Parser.hs+5−1
@@ -16,6 +16,7 @@ import Control.DeepSeq (NFData(..))
16import Control.Monad.Catch (MonadCatch)
16import Control.Monad.Catch (MonadCatch)
17import Data.Foldable (asum)
17import Data.Foldable (asum)
18import Data.Functor (($>))
18import Data.Functor (($>))
19+import Data.Maybe (fromMaybe)
19import Data.Monoid (Sum(..))
20import Data.Monoid (Sum(..))
20import System.Random (randomRIO)
21import System.Random (randomRIO)
21import Prelude
22import Prelude
@@ -74,7 +75,10 @@ drainWhile value = IP.parse (PR.drainWhile (<= value))
74
75
75{-# INLINE sliceBeginWith #-}
76{-# INLINE sliceBeginWith #-}
76sliceBeginWith :: MonadCatch m => Int -> SerialT m Int -> m ()
77sliceBeginWith :: MonadCatch m => Int -> SerialT m Int -> m ()
78+sliceBeginWith value stream = do
79+ stream1 <- return . fromMaybe (S.yield (value + 1)) =<< S.tail stream
80+ let stream2 = value `S.cons` stream1
77−sliceBeginWith value = IP.parse (PR.sliceBeginWith (>= value) FL.drain)
81+ IP.parse (PR.sliceBeginWith (== value) FL.drain) stream2
78
82
79{-# INLINE takeWhile #-}
83{-# INLINE takeWhile #-}
80takeWhile :: MonadCatch m => Int -> SerialT m Int -> m ()
84takeWhile :: MonadCatch m => Int -> SerialT m Int -> m ()
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+7−2
@@ -6,6 +6,7 @@
6-- Maintainer : streamly@composewell.com
6-- Maintainer : streamly@composewell.com
7
7
8{-# LANGUAGE FlexibleContexts #-}
8{-# LANGUAGE FlexibleContexts #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
9{-# OPTIONS_GHC -fspec-constr-recursive=4 #-}
10{-# OPTIONS_GHC -fspec-constr-recursive=4 #-}
10
11
11module Main
12module Main
@@ -17,6 +18,7 @@ import Control.DeepSeq (NFData(..))
17import Control.Monad.Catch (MonadCatch, MonadThrow)
18import Control.Monad.Catch (MonadCatch, MonadThrow)
18import Data.Foldable (asum)
19import Data.Foldable (asum)
19import Data.Functor (($>))
20import Data.Functor (($>))
21+import Data.Maybe (fromMaybe)
20import System.Random (randomRIO)
22import System.Random (randomRIO)
21import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
23import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
22
24
@@ -64,8 +66,11 @@ drainWhile :: MonadThrow m => (a -> Bool) -> PR.Parser m a ()
64drainWhile p = PR.takeWhile p FL.drain
66drainWhile p = PR.takeWhile p FL.drain
65
67
66{-# INLINE sliceBeginWith #-}
68{-# INLINE sliceBeginWith #-}
67−sliceBeginWith :: MonadCatch m => Int -> SerialT m Int -> m()
69+sliceBeginWith :: MonadCatch m => Int -> SerialT m Int -> m ()
70+sliceBeginWith value stream = do
71+ stream1 <- return . fromMaybe (S.yield (value + 1)) =<< S.tail stream
72+ let stream2 = value `S.cons` stream1
68−sliceBeginWith value = IP.parseD (PR.sliceBeginWith (>= value) FL.drain)
73+ IP.parseD (PR.sliceBeginWith (== value) FL.drain) stream2
69
74
70{-# INLINE takeWhile #-}
75{-# INLINE takeWhile #-}
71takeWhile :: MonadThrow m => Int -> SerialT m Int -> m ()
76takeWhile :: MonadThrow m => Int -> SerialT m Int -> m ()
src/Streamly/Internal/Data/Parser/ParserD.hs+11−2
@@ -547,7 +547,12 @@ sliceBeginWith cond (Fold fstep finitial fextract) =
547
547
548 where
548 where
549
549
550− initial = Left' <$> finitial
550+ initial = do
551+ res <- finitial
552+ return $
553+ case res of
554+ FL.Partial s -> Left' s
555+ FL.Done _ -> error "sliceBeginWith : bad finitial"
551
556
552 {-# INLINE process #-}
557 {-# INLINE process #-}
553 process s a = do
558 process s a = do
@@ -557,7 +562,11 @@ sliceBeginWith cond (Fold fstep finitial fextract) =
557 FL.Partial s1 -> Partial 0 (Right' s1)
562 FL.Partial s1 -> Partial 0 (Right' s1)
558 FL.Done b -> Done 0 b
563 FL.Done b -> Done 0 b
559
564
560− step (Left' s) a = process s a
565+ step (Left' s) a =
566+ if cond a
567+ then process s a
568+ else error $ "sliceBeginWith : slice begins with an element which"
569+ ++ "fails the predicate"
561 step (Right' s) a =
570 step (Right' s) a =
562 if not (cond a)
571 if not (cond a)
563 then process s a
572 then process s a
test/Streamly/Test/Data/Parser.hs+15−13
@@ -326,20 +326,22 @@ sliceSepByP =
326sliceBeginWith :: Property
326sliceBeginWith :: Property
327sliceBeginWith =
327sliceBeginWith =
328 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
328 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
329+ let ls1 = 1:ls
330+ in
329− case S.parse parser (S.fromList ls) of
331+ case S.parse parser (S.fromList ls1) of
330− Right parsed_list ->
332+ Right parsed_list ->
331− if not $ Prelude.null ls
333+ if not $ Prelude.null ls1
332− then
334+ then
333− let tls = Prelude.takeWhile (not . predicate) (tail ls)
335+ let tls = Prelude.takeWhile (not . predicate) (tail ls1)
334 in checkListEqual parsed_list $
336 in checkListEqual parsed_list $
335− if predicate (head ls)
337+ if predicate (head ls1)
336− then head ls : tls
338+ then head ls1 : tls
337− else Prelude.takeWhile (not . predicate) ls
339+ else Prelude.takeWhile (not . predicate) ls1
338− else property $ Prelude.null parsed_list
340+ else property $ Prelude.null parsed_list
339− Left _ -> property False
341+ Left _ -> property False
340− where
342+ where
341− predicate = odd
343+ predicate = odd
342− parser = P.sliceBeginWith predicate FL.toList
344+ parser = P.sliceBeginWith predicate FL.toList
343
345
344takeWhile :: Property
346takeWhile :: Property
345takeWhile =
347takeWhile =