on 32785ad help sign in
3122 lines 115 kB history raw
1-- |
2-- Module : Streamly.Internal.Data.Stream.StreamD.Nesting
3-- Copyright : (c) 2018 Composewell Technologies
4-- (c) Roman Leshchinskiy 2008-2010
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
8-- Portability : GHC
9--
10-- This module contains transformations involving multiple streams, unfolds or
11-- folds. There are two types of transformations generational or eliminational.
12-- Generational transformations are like the "Generate" module but they
13-- generate a stream by combining streams instead of elements. Eliminational
14-- transformations are like the "Eliminate" module but they transform a stream
15-- by eliminating parts of the stream instead of eliminating the whole stream.
16--
17-- These combinators involve transformation, generation, elimination so can be
18-- classified under any of those.
19--
20-- Ultimately these operations should be supported by Unfolds, Pipes and Folds,
21-- and this module may become redundant.
23-- The zipWithM combinator in this module has been adapted from the vector
24-- package (c) Roman Leshchinskiy.
25--
26module Streamly.Internal.Data.Stream.StreamD.Nesting
27 (
28 -- * Generate
29 -- | Combining streams to generate streams.
31 -- ** Combine Two Streams
32 -- | Functions ending in the shape:
33 --
34 -- @t m a -> t m a -> t m a@.
36 -- *** Appending
37 -- | Append a stream after another. A special case of concatMap or
38 -- unfoldMany.
39 AppendState(..)
40 , append
42 -- *** Interleaving
43 -- | Interleave elements from two streams alternately. A special case of
44 -- unfoldInterleave.
45 , InterleaveState(..)
46 , interleave
47 , interleaveMin
48 , interleaveFst
49 , interleaveFstSuffix
51 -- *** Scheduling
52 -- | Execute streams alternately irrespective of whether they generate
53 -- elements or not. Note 'interleave' would execute a stream until it
54 -- yields an element. A special case of unfoldRoundRobin.
55 , roundRobin -- interleaveFair?/ParallelFair
57 -- *** Zipping
58 -- | Zip corresponding elements of two streams.
59 , zipWith
60 , zipWithM
62 -- *** Merging
63 -- | Interleave elements from two streams based on a condition.
64 , mergeBy
65 , mergeByM
66 , mergeMinBy
67 , mergeFstBy
69 -- ** Combine N Streams
70 -- | Functions generally ending in these shapes:
71 --
72 -- @
73 -- concat: f (t m a) -> t m a
74 -- concatMap: (a -> t m b) -> t m a -> t m b
75 -- unfoldMany: Unfold m a b -> t m a -> t m b
76 -- @
78 -- *** ConcatMap
79 -- | Generate streams by mapping a stream generator on each element of an
80 -- input stream, append the resulting streams and flatten.
81 , concatMap
82 , concatMapM
84 -- *** ConcatUnfold
85 -- | Generate streams by using an unfold on each element of an input
86 -- stream, append the resulting streams and flatten. A special case of
87 -- gintercalate.
88 , unfoldMany
89 , ConcatUnfoldInterleaveState (..)
90 , unfoldInterleave
91 , unfoldRoundRobin
93 -- *** Interpose
94 -- | Like unfoldMany but intersperses an effect between the streams. A
95 -- special case of gintercalate.
96 , interpose
97 , interposeM
98 , interposeSuffix
99 , interposeSuffixM
101 -- *** Intercalate
102 -- | Like unfoldMany but intersperses streams from another source between
103 -- the streams from the first source.
104 , gintercalate
105 , gintercalateSuffix
106 , intercalate
107 , intercalateSuffix
109 -- * Eliminate
110 -- | Folding and Parsing chunks of streams to eliminate nested streams.
111 -- Functions generally ending in these shapes:
112 --
113 -- @
114 -- f (Fold m a b) -> t m a -> t m b
115 -- f (Parser a m b) -> t m a -> t m b
116 -- @
118 -- ** Folding
119 -- | Apply folds on a stream.
120 , foldMany
121 , refoldMany
122 , foldSequence
123 , foldIterateM
124 , refoldIterateM
126 -- ** Parsing
127 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
128 -- unfoldMany. concatMap generates a stream from single values in a
129 -- stream and flattens, parseMany does the opposite of flattening by
130 -- splitting the stream and then folds each such split to single value in
131 -- the output stream.
132 , parseMany
133 , parseManyD
134 , parseSequence
135 , parseManyTill
136 , parseIterate
137 , parseIterateD
139 -- ** Grouping
140 -- | Group segments of a stream and fold. Special case of parsing.
141 , chunksOf
142 , groupsBy
143 , groupsRollingBy
145 -- ** Splitting
146 -- | A special case of parsing.
147 , wordsBy
148 , splitOnSeq
149 , splitOnSuffixSeq
150 , sliceOnSuffix
152 -- XXX Implement these as folds or parsers instead.
153 , splitOnSuffixSeqAny
154 , splitOnPrefix
155 , splitOnAny
157 -- * Transform (Nested Containers)
158 -- | Opposite to compact in ArrayStream
159 , splitInnerBy
160 , splitInnerBySuffix
161 , intersectBySorted
163 -- * Reduce By Streams
164 , dropPrefix
165 , dropInfix
166 , dropSuffix
167 )
168where
170#include "inline.hs"
171#include "ArrayMacros.h"
173import Control.Exception (assert)
174import Control.Monad.IO.Class (MonadIO(..))
175import Data.Bits (shiftR, shiftL, (.|.), (.&.))
176import Data.Proxy (Proxy(..))
177import Data.Word (Word32)
178import Foreign.Storable (Storable, peek)
179import Fusion.Plugin.Types (Fuse(..))
180import GHC.Types (SPEC(..))
182import Streamly.Internal.Data.Array.Type (Array(..))
183import Streamly.Internal.Data.Fold.Step (Step(..))
184import Streamly.Internal.Data.Fold.Type (Fold(..))
185import Streamly.Internal.Data.Parser (ParseError(..))
186import Streamly.Internal.Data.Refold.Type (Refold(..))
187import Streamly.Internal.Data.SVar.Type (adaptState)
188import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
189import Streamly.Internal.Data.Unboxed (Unbox, sizeOf)
190import Streamly.Internal.Data.Unfold.Type (Unfold(..))
192import qualified Streamly.Internal.Data.Array.Type as A
193import qualified Streamly.Internal.Data.Fold as FL
194import qualified Streamly.Internal.Data.Parser as PR
195import qualified Streamly.Internal.Data.Parser.ParserD as PRD
196import qualified Streamly.Internal.Data.Ring.Unboxed as RB
198import Streamly.Internal.Data.Stream.StreamD.Transform
199 (intersperse, intersperseMSuffix)
200import Streamly.Internal.Data.Stream.StreamD.Type
202import Prelude hiding (concatMap, mapM, zipWith)
204-- $setup
205-- >>> :m
206-- >>> import Data.Either (either)
207-- >>> import Data.IORef
208-- >>> import Streamly.Internal.Data.Stream (Stream)
209-- >>> import Prelude hiding (zipWith, concatMap, concat)
210-- >>> import qualified Streamly.Data.Array as Array
211-- >>> import qualified Streamly.Internal.Data.Fold as Fold
212-- >>> import qualified Streamly.Internal.Data.Stream as Stream
213-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
214-- >>> import qualified Streamly.Internal.Data.Parser as Parser
215-- >>> import qualified Streamly.Internal.FileSystem.Dir as Dir
216--
218------------------------------------------------------------------------------
219-- Appending
220------------------------------------------------------------------------------
222data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
224-- | Fuses two streams sequentially, yielding all elements from the first
225-- stream, and then all elements from the second stream.
226--
227-- >>> s1 = Stream.fromList [1,2]
228-- >>> s2 = Stream.fromList [3,4]
229-- >>> Stream.fold Fold.toList $ s1 `Stream.append` s2
230-- [1,2,3,4]
231--
232-- This function should not be used to dynamically construct a stream. If a
233-- stream is constructed by successive use of this function it would take
234-- quadratic time complexity to consume the stream.
235--
236-- This function should only be used to statically fuse a stream with another
237-- stream. Do not use this recursively or where it cannot be inlined.
238--
239-- See "Streamly.Data.Stream.StreamK" for an 'append' that can be used to
240-- construct a stream recursively.
241--
242{-# INLINE_NORMAL append #-}
243append :: Monad m => Stream m a -> Stream m a -> Stream m a
244append (Stream step1 state1) (Stream step2 state2) =
245 Stream step (AppendFirst state1)
247 where
249 {-# INLINE_LATE step #-}
250 step gst (AppendFirst st) = do
251 r <- step1 gst st
252 return $ case r of
253 Yield a s -> Yield a (AppendFirst s)
254 Skip s -> Skip (AppendFirst s)
255 Stop -> Skip (AppendSecond state2)
257 step gst (AppendSecond st) = do
258 r <- step2 gst st
259 return $ case r of
260 Yield a s -> Yield a (AppendSecond s)
261 Skip s -> Skip (AppendSecond s)
262 Stop -> Stop
264------------------------------------------------------------------------------
265-- Interleaving
266------------------------------------------------------------------------------
268data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
269 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
271-- | Interleaves two streams, yielding one element from each stream
272-- alternately. When one stream stops the rest of the other stream is used in
273-- the output stream.
274--
275-- When joining many streams in a left associative manner earlier streams will
276-- get exponential priority than the ones joining later. Because of exponential
277-- weighting it can be used with 'concatMapWith' even on a large number of
278-- streams.
279--
280{-# INLINE_NORMAL interleave #-}
281interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
282interleave (Stream step1 state1) (Stream step2 state2) =
283 Stream step (InterleaveFirst state1 state2)
285 where
287 {-# INLINE_LATE step #-}
288 step gst (InterleaveFirst st1 st2) = do
289 r <- step1 gst st1
290 return $ case r of
291 Yield a s -> Yield a (InterleaveSecond s st2)
292 Skip s -> Skip (InterleaveFirst s st2)
293 Stop -> Skip (InterleaveSecondOnly st2)
295 step gst (InterleaveSecond st1 st2) = do
296 r <- step2 gst st2
297 return $ case r of
298 Yield a s -> Yield a (InterleaveFirst st1 s)
299 Skip s -> Skip (InterleaveSecond st1 s)
300 Stop -> Skip (InterleaveFirstOnly st1)
302 step gst (InterleaveFirstOnly st1) = do
303 r <- step1 gst st1
304 return $ case r of
305 Yield a s -> Yield a (InterleaveFirstOnly s)
306 Skip s -> Skip (InterleaveFirstOnly s)
307 Stop -> Stop
309 step gst (InterleaveSecondOnly st2) = do
310 r <- step2 gst st2
311 return $ case r of
312 Yield a s -> Yield a (InterleaveSecondOnly s)
313 Skip s -> Skip (InterleaveSecondOnly s)
314 Stop -> Stop
316-- | Like `interleave` but stops interleaving as soon as any of the two streams
317-- stops.
318--
319{-# INLINE_NORMAL interleaveMin #-}
320interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
321interleaveMin (Stream step1 state1) (Stream step2 state2) =
322 Stream step (InterleaveFirst state1 state2)
324 where
326 {-# INLINE_LATE step #-}
327 step gst (InterleaveFirst st1 st2) = do
328 r <- step1 gst st1
329 return $ case r of
330 Yield a s -> Yield a (InterleaveSecond s st2)
331 Skip s -> Skip (InterleaveFirst s st2)
332 Stop -> Stop
334 step gst (InterleaveSecond st1 st2) = do
335 r <- step2 gst st2
336 return $ case r of
337 Yield a s -> Yield a (InterleaveFirst st1 s)
338 Skip s -> Skip (InterleaveSecond st1 s)
339 Stop -> Stop
341 step _ (InterleaveFirstOnly _) = undefined
342 step _ (InterleaveSecondOnly _) = undefined
344-- | Interleaves the outputs of two streams, yielding elements from each stream
345-- alternately, starting from the first stream. As soon as the first stream
346-- finishes, the output stops, discarding the remaining part of the second
347-- stream. In this case, the last element in the resulting stream would be from
348-- the second stream. If the second stream finishes early then the first stream
349-- still continues to yield elements until it finishes.
350--
351-- >>> :set -XOverloadedStrings
352-- >>> import Data.Functor.Identity (Identity)
353-- >>> Stream.interleaveFstSuffix "abc" ",,,," :: Stream Identity Char
354-- fromList "a,b,c,"
355-- >>> Stream.interleaveFstSuffix "abc" "," :: Stream Identity Char
356-- fromList "a,bc"
357--
358-- 'interleaveFstSuffix' is a dual of 'interleaveFst'.
359--
360-- Do not use dynamically.
361--
362-- /Pre-release/
363{-# INLINE_NORMAL interleaveFstSuffix #-}
364interleaveFstSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
365interleaveFstSuffix (Stream step1 state1) (Stream step2 state2) =
366 Stream step (InterleaveFirst state1 state2)
368 where
370 {-# INLINE_LATE step #-}
371 step gst (InterleaveFirst st1 st2) = do
372 r <- step1 gst st1
373 return $ case r of
374 Yield a s -> Yield a (InterleaveSecond s st2)
375 Skip s -> Skip (InterleaveFirst s st2)
376 Stop -> Stop
378 step gst (InterleaveSecond st1 st2) = do
379 r <- step2 gst st2
380 return $ case r of
381 Yield a s -> Yield a (InterleaveFirst st1 s)
382 Skip s -> Skip (InterleaveSecond st1 s)
383 Stop -> Skip (InterleaveFirstOnly st1)
385 step gst (InterleaveFirstOnly st1) = do
386 r <- step1 gst st1
387 return $ case r of
388 Yield a s -> Yield a (InterleaveFirstOnly s)
389 Skip s -> Skip (InterleaveFirstOnly s)
390 Stop -> Stop
392 step _ (InterleaveSecondOnly _) = undefined
394data InterleaveInfixState s1 s2 a
395 = InterleaveInfixFirst s1 s2
396 | InterleaveInfixSecondBuf s1 s2
397 | InterleaveInfixSecondYield s1 s2 a
398 | InterleaveInfixFirstYield s1 s2 a
399 | InterleaveInfixFirstOnly s1
401-- | Interleaves the outputs of two streams, yielding elements from each stream
402-- alternately, starting from the first stream and ending at the first stream.
403-- If the second stream is longer than the first, elements from the second
404-- stream are infixed with elements from the first stream. If the first stream
405-- is longer then it continues yielding elements even after the second stream
406-- has finished.
407--
408-- >>> :set -XOverloadedStrings
409-- >>> import Data.Functor.Identity (Identity)
410-- >>> Stream.interleaveFst "abc" ",,,," :: Stream Identity Char
411-- fromList "a,b,c"
412-- >>> Stream.interleaveFst "abc" "," :: Stream Identity Char
413-- fromList "a,bc"
414--
415-- 'interleaveFst' is a dual of 'interleaveFstSuffix'.
416--
417-- Do not use dynamically.
418--
419-- /Pre-release/
420{-# INLINE_NORMAL interleaveFst #-}
421interleaveFst :: Monad m => Stream m a -> Stream m a -> Stream m a
422interleaveFst (Stream step1 state1) (Stream step2 state2) =
423 Stream step (InterleaveInfixFirst state1 state2)
425 where
427 {-# INLINE_LATE step #-}
428 step gst (InterleaveInfixFirst st1 st2) = do
429 r <- step1 gst st1
430 return $ case r of
431 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
432 Skip s -> Skip (InterleaveInfixFirst s st2)
433 Stop -> Stop
435 step gst (InterleaveInfixSecondBuf st1 st2) = do
436 r <- step2 gst st2
437 return $ case r of
438 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
439 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
440 Stop -> Skip (InterleaveInfixFirstOnly st1)
442 step gst (InterleaveInfixSecondYield st1 st2 x) = do
443 r <- step1 gst st1
444 return $ case r of
445 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
446 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
447 Stop -> Stop
449 step _ (InterleaveInfixFirstYield st1 st2 x) = do
450 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
452 step gst (InterleaveInfixFirstOnly st1) = do
453 r <- step1 gst st1
454 return $ case r of
455 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
456 Skip s -> Skip (InterleaveInfixFirstOnly s)
457 Stop -> Stop
459------------------------------------------------------------------------------
460-- Scheduling
461------------------------------------------------------------------------------
463-- | Schedule the execution of two streams in a fair round-robin manner,
464-- executing each stream once, alternately. Execution of a stream may not
465-- necessarily result in an output, a stream may choose to @Skip@ producing an
466-- element until later giving the other stream a chance to run. Therefore, this
467-- combinator fairly interleaves the execution of two streams rather than
468-- fairly interleaving the output of the two streams. This can be useful in
469-- co-operative multitasking without using explicit threads. This can be used
470-- as an alternative to `async`.
471--
472-- Do not use dynamically.
473--
474-- /Pre-release/
475{-# INLINE_NORMAL roundRobin #-}
476roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
477roundRobin (Stream step1 state1) (Stream step2 state2) =
478 Stream step (InterleaveFirst state1 state2)
480 where
482 {-# INLINE_LATE step #-}
483 step gst (InterleaveFirst st1 st2) = do
484 r <- step1 gst st1
485 return $ case r of
486 Yield a s -> Yield a (InterleaveSecond s st2)
487 Skip s -> Skip (InterleaveSecond s st2)
488 Stop -> Skip (InterleaveSecondOnly st2)
490 step gst (InterleaveSecond st1 st2) = do
491 r <- step2 gst st2
492 return $ case r of
493 Yield a s -> Yield a (InterleaveFirst st1 s)
494 Skip s -> Skip (InterleaveFirst st1 s)
495 Stop -> Skip (InterleaveFirstOnly st1)
497 step gst (InterleaveSecondOnly st2) = do
498 r <- step2 gst st2
499 return $ case r of
500 Yield a s -> Yield a (InterleaveSecondOnly s)
501 Skip s -> Skip (InterleaveSecondOnly s)
502 Stop -> Stop
504 step gst (InterleaveFirstOnly st1) = do
505 r <- step1 gst st1
506 return $ case r of
507 Yield a s -> Yield a (InterleaveFirstOnly s)
508 Skip s -> Skip (InterleaveFirstOnly s)
509 Stop -> Stop
511------------------------------------------------------------------------------
512-- Merging
513------------------------------------------------------------------------------
515-- | Like 'mergeBy' but with a monadic comparison function.
516--
517-- Merge two streams randomly:
518--
519-- @
520-- > randomly _ _ = randomIO >>= \x -> return $ if x then LT else GT
521-- > Stream.toList $ Stream.mergeByM randomly (Stream.fromList [1,1,1,1]) (Stream.fromList [2,2,2,2])
522-- [2,1,2,2,2,1,1,1]
523-- @
524--
525-- Merge two streams in a proportion of 2:1:
526--
527-- >>> :{
528-- do
529-- let s1 = Stream.fromList [1,1,1,1,1,1]
530-- s2 = Stream.fromList [2,2,2]
531-- let proportionately m n = do
532-- ref <- newIORef $ cycle $ Prelude.concat [Prelude.replicate m LT, Prelude.replicate n GT]
533-- return $ \_ _ -> do
534-- r <- readIORef ref
535-- writeIORef ref $ Prelude.tail r
536-- return $ Prelude.head r
537-- f <- proportionately 2 1
538-- xs <- Stream.fold Fold.toList $ Stream.mergeByM f s1 s2
539-- print xs
540-- :}
541-- [1,1,2,1,1,2,1,1,2]
542--
543{-# INLINE_NORMAL mergeByM #-}
544mergeByM
545 :: (Monad m)
546 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
547mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
548 Stream step (Just ta, Just tb, Nothing, Nothing)
549 where
550 {-# INLINE_LATE step #-}
552 -- one of the values is missing, and the corresponding stream is running
553 step gst (Just sa, sb, Nothing, b) = do
554 r <- stepa gst sa
555 return $ case r of
556 Yield a sa' -> Skip (Just sa', sb, Just a, b)
557 Skip sa' -> Skip (Just sa', sb, Nothing, b)
558 Stop -> Skip (Nothing, sb, Nothing, b)
560 step gst (sa, Just sb, a, Nothing) = do
561 r <- stepb gst sb
562 return $ case r of
563 Yield b sb' -> Skip (sa, Just sb', a, Just b)
564 Skip sb' -> Skip (sa, Just sb', a, Nothing)
565 Stop -> Skip (sa, Nothing, a, Nothing)
567 -- both the values are available
568 step _ (sa, sb, Just a, Just b) = do
569 res <- cmp a b
570 return $ case res of
571 GT -> Yield b (sa, sb, Just a, Nothing)
572 _ -> Yield a (sa, sb, Nothing, Just b)
574 -- one of the values is missing, corresponding stream is done
575 step _ (Nothing, sb, Nothing, Just b) =
576 return $ Yield b (Nothing, sb, Nothing, Nothing)
578 step _ (sa, Nothing, Just a, Nothing) =
579 return $ Yield a (sa, Nothing, Nothing, Nothing)
581 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
583-- | Merge two streams using a comparison function. The head elements of both
584-- the streams are compared and the smaller of the two elements is emitted, if
585-- both elements are equal then the element from the first stream is used
586-- first.
587--
588-- If the streams are sorted in ascending order, the resulting stream would
589-- also remain sorted in ascending order.
590--
591-- >>> s1 = Stream.fromList [1,3,5]
592-- >>> s2 = Stream.fromList [2,4,6,8]
593-- >>> Stream.fold Fold.toList $ Stream.mergeBy compare s1 s2
594-- [1,2,3,4,5,6,8]
595--
596{-# INLINE mergeBy #-}
597mergeBy
598 :: (Monad m)
599 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
600mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
602-- | Like 'mergeByM' but stops merging as soon as any of the two streams stops.
603--
604-- /Unimplemented/
605{-# INLINABLE mergeMinBy #-}
606mergeMinBy :: -- Monad m =>
607 (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
608mergeMinBy _f _m1 _m2 = undefined
609 -- fromStreamD $ D.mergeMinBy f (toStreamD m1) (toStreamD m2)
611-- | Like 'mergeByM' but stops merging as soon as the first stream stops.
612--
613-- /Unimplemented/
614{-# INLINABLE mergeFstBy #-}
615mergeFstBy :: -- Monad m =>
616 (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
617mergeFstBy _f _m1 _m2 = undefined
618 -- fromStreamK $ D.mergeFstBy f (toStreamD m1) (toStreamD m2)
620-------------------------------------------------------------------------------
621-- Intersection of sorted streams
622-------------------------------------------------------------------------------
624-- Assuming the streams are sorted in ascending order
625{-# INLINE_NORMAL intersectBySorted #-}
626intersectBySorted :: Monad m
627 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
628intersectBySorted cmp (Stream stepa ta) (Stream stepb tb) =
629 Stream step
630 ( ta -- left stream state
631 , tb -- right stream state
632 , Nothing -- left value
633 , Nothing -- right value
634 )
636 where
638 {-# INLINE_LATE step #-}
639 -- step 1, fetch the first value
640 step gst (sa, sb, Nothing, b) = do
641 r <- stepa gst sa
642 return $ case r of
643 Yield a sa' -> Skip (sa', sb, Just a, b) -- step 2/3
644 Skip sa' -> Skip (sa', sb, Nothing, b)
645 Stop -> Stop
647 -- step 2, fetch the second value
648 step gst (sa, sb, a@(Just _), Nothing) = do
649 r <- stepb gst sb
650 return $ case r of
651 Yield b sb' -> Skip (sa, sb', a, Just b) -- step 3
652 Skip sb' -> Skip (sa, sb', a, Nothing)
653 Stop -> Stop
655 -- step 3, compare the two values
656 step _ (sa, sb, Just a, Just b) = do
657 let res = cmp a b
658 return $ case res of
659 GT -> Skip (sa, sb, Just a, Nothing) -- step 2
660 LT -> Skip (sa, sb, Nothing, Just b) -- step 1
661 EQ -> Yield a (sa, sb, Nothing, Just b) -- step 1
663------------------------------------------------------------------------------
664-- Combine N Streams - unfoldMany
665------------------------------------------------------------------------------
667data ConcatUnfoldInterleaveState o i =
668 ConcatUnfoldInterleaveOuter o [i]
669 | ConcatUnfoldInterleaveInner o [i]
670 | ConcatUnfoldInterleaveInnerL [i] [i]
671 | ConcatUnfoldInterleaveInnerR [i] [i]
673-- XXX use arrays to store state instead of lists?
674--
675-- XXX In general we can use different scheduling strategies e.g. how to
676-- schedule the outer vs inner loop or assigning weights to different streams
677-- or outer and inner loops.
679-- After a yield, switch to the next stream. Do not switch streams on Skip.
680-- Yield from outer stream switches to the inner stream.
681--
682-- There are two choices here, (1) exhaust the outer stream first and then
683-- start yielding from the inner streams, this is much simpler to implement,
684-- (2) yield at least one element from an inner stream before going back to
685-- outer stream and opening the next stream from it.
686--
687-- Ideally, we need some scheduling bias to inner streams vs outer stream.
688-- Maybe we can configure the behavior.
689--
690-- XXX Instead of using "concatPairsWith wSerial" we can implement an N-way
691-- interleaving CPS combinator which behaves like unfoldInterleave. Instead
692-- of pairing up the streams we just need to go yielding one element from each
693-- stream and storing the remaining streams and then keep doing rounds through
694-- those in a round robin fashion. This would be much like wAsync.
696-- | This does not pair streams like mergeMapWith, instead, it goes through
697-- each stream one by one and yields one element from each stream. After it
698-- goes to the last stream it reverses the traversal to come back to the first
699-- stream yielding elements from each stream on its way back to the first
700-- stream and so on.
701--
702-- >>> lists = Stream.fromList [[1,1],[2,2],[3,3],[4,4],[5,5]]
703-- >>> interleaved = Stream.unfoldInterleave Unfold.fromList lists
704-- >>> Stream.fold Fold.toList interleaved
705-- [1,2,3,4,5,5,4,3,2,1]
706--
707-- Note that this is order of magnitude more efficient than "mergeMapWith
708-- interleave" because of fusion.
709--
710{-# INLINE_NORMAL unfoldInterleave #-}
711unfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
712unfoldInterleave (Unfold istep inject) (Stream ostep ost) =
713 Stream step (ConcatUnfoldInterleaveOuter ost [])
715 where
717 {-# INLINE_LATE step #-}
718 step gst (ConcatUnfoldInterleaveOuter o ls) = do
719 r <- ostep (adaptState gst) o
720 case r of
721 Yield a o' -> do
722 i <- inject a
723 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
724 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
725 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
727 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
728 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
729 r <- istep st
730 return $ case r of
731 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
732 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
733 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
735 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
736 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
737 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
739 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
740 r <- istep st
741 return $ case r of
742 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
743 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
744 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
746 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
747 step _ (ConcatUnfoldInterleaveInnerR ls []) =
748 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
750 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
751 r <- istep st
752 return $ case r of
753 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
754 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
755 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
757-- XXX In general we can use different scheduling strategies e.g. how to
758-- schedule the outer vs inner loop or assigning weights to different streams
759-- or outer and inner loops.
760--
761-- This could be inefficient if the tasks are too small.
762--
763-- Compared to unfoldInterleave this one switches streams on Skips.
765-- | 'unfoldInterleave' switches to the next stream whenever a value from a
766-- stream is yielded, it does not switch on a 'Skip'. So if a stream keeps
767-- skipping for long time other streams won't get a chance to run.
768-- 'unfoldRoundRobin' switches on Skip as well. So it basically schedules each
769-- stream fairly irrespective of whether it produces a value or not.
770--
771{-# INLINE_NORMAL unfoldRoundRobin #-}
772unfoldRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
773unfoldRoundRobin (Unfold istep inject) (Stream ostep ost) =
774 Stream step (ConcatUnfoldInterleaveOuter ost [])
775 where
776 {-# INLINE_LATE step #-}
777 step gst (ConcatUnfoldInterleaveOuter o ls) = do
778 r <- ostep (adaptState gst) o
779 case r of
780 Yield a o' -> do
781 i <- inject a
782 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
783 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
784 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
786 step _ (ConcatUnfoldInterleaveInner o []) =
787 return $ Skip (ConcatUnfoldInterleaveOuter o [])
789 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
790 r <- istep st
791 return $ case r of
792 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
793 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
794 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
796 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
797 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
798 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
800 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
801 r <- istep st
802 return $ case r of
803 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
804 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
805 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
807 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
808 step _ (ConcatUnfoldInterleaveInnerR ls []) =
809 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
811 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
812 r <- istep st
813 return $ case r of
814 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
815 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
816 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
818------------------------------------------------------------------------------
819-- Combine N Streams - interpose
820------------------------------------------------------------------------------
822{-# ANN type InterposeSuffixState Fuse #-}
823data InterposeSuffixState s1 i1 =
824 InterposeSuffixFirst s1
825 -- | InterposeSuffixFirstYield s1 i1
826 | InterposeSuffixFirstInner s1 i1
827 | InterposeSuffixSecond s1
829-- Note that if an unfolded layer turns out to be nil we still emit the
830-- separator effect. An alternate behavior could be to emit the separator
831-- effect only if at least one element has been yielded by the unfolding.
832-- However, that becomes a bit complicated, so we have chosen the former
833-- behvaior for now.
834{-# INLINE_NORMAL interposeSuffixM #-}
835interposeSuffixM
836 :: Monad m
837 => m c -> Unfold m b c -> Stream m b -> Stream m c
838interposeSuffixM
839 action
840 (Unfold istep1 inject1) (Stream step1 state1) =
841 Stream step (InterposeSuffixFirst state1)
843 where
845 {-# INLINE_LATE step #-}
846 step gst (InterposeSuffixFirst s1) = do
847 r <- step1 (adaptState gst) s1
848 case r of
849 Yield a s -> do
850 i <- inject1 a
851 i `seq` return (Skip (InterposeSuffixFirstInner s i))
852 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
853 Skip s -> return $ Skip (InterposeSuffixFirst s)
854 Stop -> return Stop
856 {-
857 step _ (InterposeSuffixFirstYield s1 i1) = do
858 r <- istep1 i1
859 return $ case r of
860 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
861 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
862 Stop -> Skip (InterposeSuffixFirst s1)
863 -}
865 step _ (InterposeSuffixFirstInner s1 i1) = do
866 r <- istep1 i1
867 return $ case r of
868 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
869 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
870 Stop -> Skip (InterposeSuffixSecond s1)
872 step _ (InterposeSuffixSecond s1) = do
873 r <- action
874 return $ Yield r (InterposeSuffixFirst s1)
876-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
878-- | Unfold the elements of a stream, append the given element after each
879-- unfolded stream and then concat them into a single stream.
880--
881-- >>> unlines = Stream.interposeSuffix '\n'
882--
883-- /Pre-release/
884{-# INLINE interposeSuffix #-}
885interposeSuffix :: Monad m
886 => c -> Unfold m b c -> Stream m b -> Stream m c
887interposeSuffix x = interposeSuffixM (return x)
889{-# ANN type InterposeState Fuse #-}
890data InterposeState s1 i1 a =
891 InterposeFirst s1
892 -- | InterposeFirstYield s1 i1
893 | InterposeFirstInner s1 i1
894 | InterposeFirstInject s1
895 -- | InterposeFirstBuf s1 i1
896 | InterposeSecondYield s1 i1
897 -- -- | InterposeSecondYield s1 i1 a
898 -- -- | InterposeFirstResume s1 i1 a
900-- Note that this only interposes the pure values, we may run many effects to
901-- generate those values as some effects may not generate anything (Skip).
902{-# INLINE_NORMAL interposeM #-}
903interposeM :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
904interposeM
905 action
906 (Unfold istep1 inject1) (Stream step1 state1) =
907 Stream step (InterposeFirst state1)
909 where
911 {-# INLINE_LATE step #-}
912 step gst (InterposeFirst s1) = do
913 r <- step1 (adaptState gst) s1
914 case r of
915 Yield a s -> do
916 i <- inject1 a
917 i `seq` return (Skip (InterposeFirstInner s i))
918 -- i `seq` return (Skip (InterposeFirstYield s i))
919 Skip s -> return $ Skip (InterposeFirst s)
920 Stop -> return Stop
922 {-
923 step _ (InterposeFirstYield s1 i1) = do
924 r <- istep1 i1
925 return $ case r of
926 Yield x i' -> Yield x (InterposeFirstInner s1 i')
927 Skip i' -> Skip (InterposeFirstYield s1 i')
928 Stop -> Skip (InterposeFirst s1)
929 -}
931 step _ (InterposeFirstInner s1 i1) = do
932 r <- istep1 i1
933 return $ case r of
934 Yield x i' -> Yield x (InterposeFirstInner s1 i')
935 Skip i' -> Skip (InterposeFirstInner s1 i')
936 Stop -> Skip (InterposeFirstInject s1)
938 step gst (InterposeFirstInject s1) = do
939 r <- step1 (adaptState gst) s1
940 case r of
941 Yield a s -> do
942 i <- inject1 a
943 -- i `seq` return (Skip (InterposeFirstBuf s i))
944 i `seq` return (Skip (InterposeSecondYield s i))
945 Skip s -> return $ Skip (InterposeFirstInject s)
946 Stop -> return Stop
948 {-
949 step _ (InterposeFirstBuf s1 i1) = do
950 r <- istep1 i1
951 return $ case r of
952 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
953 Skip i' -> Skip (InterposeFirstBuf s1 i')
954 Stop -> Stop
955 -}
957 {-
958 step _ (InterposeSecondYield s1 i1 v) = do
959 r <- action
960 return $ Yield r (InterposeFirstResume s1 i1 v)
961 -}
962 step _ (InterposeSecondYield s1 i1) = do
963 r <- action
964 return $ Yield r (InterposeFirstInner s1 i1)
966 {-
967 step _ (InterposeFirstResume s1 i1 v) = do
968 return $ Yield v (InterposeFirstInner s1 i1)
969 -}
971-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
973-- | Unfold the elements of a stream, intersperse the given element between the
974-- unfolded streams and then concat them into a single stream.
975--
976-- >>> unwords = Stream.interpose ' '
977--
978-- /Pre-release/
979{-# INLINE interpose #-}
980interpose :: Monad m
981 => c -> Unfold m b c -> Stream m b -> Stream m c
982interpose x = interposeM (return x)
984------------------------------------------------------------------------------
985-- Combine N Streams - intercalate
986------------------------------------------------------------------------------
988data ICUState s1 s2 i1 i2 =
989 ICUFirst s1 s2
990 | ICUSecond s1 s2
991 | ICUSecondOnly s2
992 | ICUFirstOnly s1
993 | ICUFirstInner s1 s2 i1
994 | ICUSecondInner s1 s2 i2
995 | ICUFirstOnlyInner s1 i1
996 | ICUSecondOnlyInner s2 i2
998-- | 'interleaveFstSuffix' followed by unfold and concat.
999--
1000-- /Pre-release/
1001{-# INLINE_NORMAL gintercalateSuffix #-}
1002gintercalateSuffix
1003 :: Monad m
1004 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
1005gintercalateSuffix
1006 (Unfold istep1 inject1) (Stream step1 state1)
1007 (Unfold istep2 inject2) (Stream step2 state2) =
1008 Stream step (ICUFirst state1 state2)
1010 where
1012 {-# INLINE_LATE step #-}
1013 step gst (ICUFirst s1 s2) = do
1014 r <- step1 (adaptState gst) s1
1015 case r of
1016 Yield a s -> do
1017 i <- inject1 a
1018 i `seq` return (Skip (ICUFirstInner s s2 i))
1019 Skip s -> return $ Skip (ICUFirst s s2)
1020 Stop -> return Stop
1022 step gst (ICUFirstOnly s1) = do
1023 r <- step1 (adaptState gst) s1
1024 case r of
1025 Yield a s -> do
1026 i <- inject1 a
1027 i `seq` return (Skip (ICUFirstOnlyInner s i))
1028 Skip s -> return $ Skip (ICUFirstOnly s)
1029 Stop -> return Stop
1031 step _ (ICUFirstInner s1 s2 i1) = do
1032 r <- istep1 i1
1033 return $ case r of
1034 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
1035 Skip i' -> Skip (ICUFirstInner s1 s2 i')
1036 Stop -> Skip (ICUSecond s1 s2)
1038 step _ (ICUFirstOnlyInner s1 i1) = do
1039 r <- istep1 i1
1040 return $ case r of
1041 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
1042 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
1043 Stop -> Skip (ICUFirstOnly s1)
1045 step gst (ICUSecond s1 s2) = do
1046 r <- step2 (adaptState gst) s2
1047 case r of
1048 Yield a s -> do
1049 i <- inject2 a
1050 i `seq` return (Skip (ICUSecondInner s1 s i))
1051 Skip s -> return $ Skip (ICUSecond s1 s)
1052 Stop -> return $ Skip (ICUFirstOnly s1)
1054 step _ (ICUSecondInner s1 s2 i2) = do
1055 r <- istep2 i2
1056 return $ case r of
1057 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
1058 Skip i' -> Skip (ICUSecondInner s1 s2 i')
1059 Stop -> Skip (ICUFirst s1 s2)
1061 step _ (ICUSecondOnly _s2) = undefined
1062 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
1064data ICALState s1 s2 i1 i2 a =
1065 ICALFirst s1 s2
1066 -- | ICALFirstYield s1 s2 i1
1067 | ICALFirstInner s1 s2 i1
1068 | ICALFirstOnly s1
1069 | ICALFirstOnlyInner s1 i1
1070 | ICALSecondInject s1 s2
1071 | ICALFirstInject s1 s2 i2
1072 -- | ICALFirstBuf s1 s2 i1 i2
1073 | ICALSecondInner s1 s2 i1 i2
1074 -- -- | ICALSecondInner s1 s2 i1 i2 a
1075 -- -- | ICALFirstResume s1 s2 i1 i2 a
1077-- XXX we can swap the order of arguments to gintercalate so that the
1078-- definition of unfoldMany becomes simpler? The first stream should be
1079-- infixed inside the second one. However, if we change the order in
1080-- "interleave" as well similarly, then that will make it a bit unintuitive.
1082-- > unfoldMany unf str =
1083-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
1085-- | 'interleaveFst' followed by unfold and concat.
1087-- /Pre-release/
1088{-# INLINE_NORMAL gintercalate #-}
1089gintercalate
1090 :: Monad m
1091 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
1092gintercalate
1093 (Unfold istep1 inject1) (Stream step1 state1)
1094 (Unfold istep2 inject2) (Stream step2 state2) =
1095 Stream step (ICALFirst state1 state2)
1097 where
1099 {-# INLINE_LATE step #-}
1100 step gst (ICALFirst s1 s2) = do
1101 r <- step1 (adaptState gst) s1
1102 case r of
1103 Yield a s -> do
1104 i <- inject1 a
1105 i `seq` return (Skip (ICALFirstInner s s2 i))
1106 -- i `seq` return (Skip (ICALFirstYield s s2 i))
1107 Skip s -> return $ Skip (ICALFirst s s2)
1108 Stop -> return Stop
1110 {-
1111 step _ (ICALFirstYield s1 s2 i1) = do
1112 r <- istep1 i1
1113 return $ case r of
1114 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
1115 Skip i' -> Skip (ICALFirstYield s1 s2 i')
1116 Stop -> Skip (ICALFirst s1 s2)
1117 -}
1119 step _ (ICALFirstInner s1 s2 i1) = do
1120 r <- istep1 i1
1121 return $ case r of
1122 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
1123 Skip i' -> Skip (ICALFirstInner s1 s2 i')
1124 Stop -> Skip (ICALSecondInject s1 s2)
1126 step gst (ICALFirstOnly s1) = do
1127 r <- step1 (adaptState gst) s1
1128 case r of
1129 Yield a s -> do
1130 i <- inject1 a
1131 i `seq` return (Skip (ICALFirstOnlyInner s i))
1132 Skip s -> return $ Skip (ICALFirstOnly s)
1133 Stop -> return Stop
1135 step _ (ICALFirstOnlyInner s1 i1) = do
1136 r <- istep1 i1
1137 return $ case r of
1138 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
1139 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
1140 Stop -> Skip (ICALFirstOnly s1)
1142 -- We inject the second stream even before checking if the first stream
1143 -- would yield any more elements. There is no clear choice whether we
1144 -- should do this before or after that. Doing it after may make the state
1145 -- machine a bit simpler though.
1146 step gst (ICALSecondInject s1 s2) = do
1147 r <- step2 (adaptState gst) s2
1148 case r of
1149 Yield a s -> do
1150 i <- inject2 a
1151 i `seq` return (Skip (ICALFirstInject s1 s i))
1152 Skip s -> return $ Skip (ICALSecondInject s1 s)
1153 Stop -> return $ Skip (ICALFirstOnly s1)
1155 step gst (ICALFirstInject s1 s2 i2) = do
1156 r <- step1 (adaptState gst) s1
1157 case r of
1158 Yield a s -> do
1159 i <- inject1 a
1160 i `seq` return (Skip (ICALSecondInner s s2 i i2))
1161 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
1162 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
1163 Stop -> return Stop
1165 {-
1166 step _ (ICALFirstBuf s1 s2 i1 i2) = do
1167 r <- istep1 i1
1168 return $ case r of
1169 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
1170 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
1171 Stop -> Stop
1173 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
1174 r <- istep2 i2
1175 return $ case r of
1176 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
1177 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
1178 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
1179 -}
1181 step _ (ICALSecondInner s1 s2 i1 i2) = do
1182 r <- istep2 i2
1183 return $ case r of
1184 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
1185 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
1186 Stop -> Skip (ICALFirstInner s1 s2 i1)
1187 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
1189 {-
1190 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
1191 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
1192 -}
1194-- > intercalateSuffix unf seed str = gintercalateSuffix unf str unf (repeatM seed)
1196-- | 'intersperseMSuffix' followed by unfold and concat.
1198-- >>> intercalateSuffix u a = Stream.unfoldMany u . Stream.intersperseMSuffix a
1199-- >>> intersperseMSuffix = Stream.intercalateSuffix Unfold.identity
1200-- >>> unlines = Stream.intercalateSuffix Unfold.fromList "\n"
1202-- >>> input = Stream.fromList ["abc", "def", "ghi"]
1203-- >>> Stream.fold Fold.toList $ Stream.intercalateSuffix Unfold.fromList "\n" input
1204-- "abc\ndef\nghi\n"
1206{-# INLINE intercalateSuffix #-}
1207intercalateSuffix :: Monad m
1208 => Unfold m b c -> b -> Stream m b -> Stream m c
1209intercalateSuffix unf seed = unfoldMany unf . intersperseMSuffix (return seed)
1211-- > intercalate unf seed str = gintercalate unf str unf (repeatM seed)
1213-- | 'intersperse' followed by unfold and concat.
1215-- >>> intercalate u a = Stream.unfoldMany u . Stream.intersperse a
1216-- >>> intersperse = Stream.intercalate Unfold.identity
1217-- >>> unwords = Stream.intercalate Unfold.fromList " "
1219-- >>> input = Stream.fromList ["abc", "def", "ghi"]
1220-- >>> Stream.fold Fold.toList $ Stream.intercalate Unfold.fromList " " input
1221-- "abc def ghi"
1223{-# INLINE intercalate #-}
1224intercalate :: Monad m
1225 => Unfold m b c -> b -> Stream m b -> Stream m c
1226intercalate unf seed str = unfoldMany unf $ intersperse seed str
1228------------------------------------------------------------------------------
1229-- Folding
1230------------------------------------------------------------------------------
1232-- | Apply a stream of folds to an input stream and emit the results in the
1233-- output stream.
1235-- /Unimplemented/
1237{-# INLINE foldSequence #-}
1238foldSequence
1239 :: -- Monad m =>
1240 Stream m (Fold m a b)
1241 -> Stream m a
1242 -> Stream m b
1243foldSequence _f _m = undefined
1245{-# ANN type FIterState Fuse #-}
1246data FIterState s f m a b
1247 = FIterInit s f
1248 | forall fs. FIterStream s (fs -> a -> m (FL.Step fs b)) fs (fs -> m b)
1249 | FIterYield b (FIterState s f m a b)
1250 | FIterStop
1252-- | Iterate a fold generator on a stream. The initial value @b@ is used to
1253-- generate the first fold, the fold is applied on the stream and the result of
1254-- the fold is used to generate the next fold and so on.
1256-- >>> import Data.Monoid (Sum(..))
1257-- >>> f x = return (Fold.take 2 (Fold.sconcat x))
1258-- >>> s = fmap Sum $ Stream.fromList [1..10]
1259-- >>> Stream.fold Fold.toList $ fmap getSum $ Stream.foldIterateM f (pure 0) s
1260-- [3,10,21,36,55,55]
1262-- This is the streaming equivalent of monad like sequenced application of
1263-- folds where next fold is dependent on the previous fold.
1265-- /Pre-release/
1267{-# INLINE_NORMAL foldIterateM #-}
1268foldIterateM ::
1269 Monad m => (b -> m (FL.Fold m a b)) -> m b -> Stream m a -> Stream m b
1270foldIterateM func seed0 (Stream step state) =
1271 Stream stepOuter (FIterInit state seed0)
1273 where
1275 {-# INLINE iterStep #-}
1276 iterStep from st fstep extract = do
1277 res <- from
1278 return
1279 $ Skip
1280 $ case res of
1281 FL.Partial fs -> FIterStream st fstep fs extract
1282 FL.Done fb -> FIterYield fb $ FIterInit st (return fb)
1284 {-# INLINE_LATE stepOuter #-}
1285 stepOuter _ (FIterInit st seed) = do
1286 (FL.Fold fstep initial extract) <- seed >>= func
1287 iterStep initial st fstep extract
1288 stepOuter gst (FIterStream st fstep fs extract) = do
1289 r <- step (adaptState gst) st
1290 case r of
1291 Yield x s -> do
1292 iterStep (fstep fs x) s fstep extract
1293 Skip s -> return $ Skip $ FIterStream s fstep fs extract
1294 Stop -> do
1295 b <- extract fs
1296 return $ Skip $ FIterYield b FIterStop
1297 stepOuter _ (FIterYield a next) = return $ Yield a next
1298 stepOuter _ FIterStop = return Stop
1300{-# ANN type CIterState Fuse #-}
1301data CIterState s f fs b
1302 = CIterInit s f
1303 | CIterConsume s fs
1304 | CIterYield b (CIterState s f fs b)
1305 | CIterStop
1307-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
1308-- much more efficient due to stream fusion.
1310-- /Internal/
1311{-# INLINE_NORMAL refoldIterateM #-}
1312refoldIterateM ::
1313 Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
1314refoldIterateM (Refold fstep finject fextract) initial (Stream step state) =
1315 Stream stepOuter (CIterInit state initial)
1317 where
1319 {-# INLINE iterStep #-}
1320 iterStep st action = do
1321 res <- action
1322 return
1323 $ Skip
1324 $ case res of
1325 FL.Partial fs -> CIterConsume st fs
1326 FL.Done fb -> CIterYield fb $ CIterInit st (return fb)
1328 {-# INLINE_LATE stepOuter #-}
1329 stepOuter _ (CIterInit st action) = do
1330 iterStep st (action >>= finject)
1331 stepOuter gst (CIterConsume st fs) = do
1332 r <- step (adaptState gst) st
1333 case r of
1334 Yield x s -> iterStep s (fstep fs x)
1335 Skip s -> return $ Skip $ CIterConsume s fs
1336 Stop -> do
1337 b <- fextract fs
1338 return $ Skip $ CIterYield b CIterStop
1339 stepOuter _ (CIterYield a next) = return $ Yield a next
1340 stepOuter _ CIterStop = return Stop
1342-- "n" elements at the end are dropped by the fold.
1343{-# INLINE sliceBy #-}
1344sliceBy :: Monad m => Fold m a Int -> Int -> Refold m (Int, Int) a (Int, Int)
1345sliceBy (Fold step1 initial1 extract1) n = Refold step inject extract
1347 where
1349 inject (i, len) = do
1350 r <- initial1
1351 return $ case r of
1352 Partial s -> Partial $ Tuple' (i + len + n) s
1353 Done l -> Done (i, l)
1355 step (Tuple' i s) x = do
1356 r <- step1 s x
1357 return $ case r of
1358 Partial s1 -> Partial $ Tuple' i s1
1359 Done len -> Done (i, len)
1361 extract (Tuple' i s) = (i,) <$> extract1 s
1363{-# INLINE sliceOnSuffix #-}
1364sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
1365sliceOnSuffix predicate =
1366 -- Scan the stream with the given refold
1367 refoldIterateM
1368 (sliceBy (FL.takeEndBy_ predicate FL.length) 1)
1369 (return (-1, 0))
1371------------------------------------------------------------------------------
1372-- Parsing
1373------------------------------------------------------------------------------
1375{-# ANN type ParseChunksState Fuse #-}
1376data ParseChunksState x inpBuf st pst =
1377 ParseChunksInit inpBuf st
1378 | ParseChunksInitBuf inpBuf
1379 | ParseChunksInitLeftOver inpBuf
1380 | ParseChunksStream st inpBuf !pst
1381 | ParseChunksStop inpBuf !pst
1382 | ParseChunksBuf inpBuf st inpBuf !pst
1383 | ParseChunksExtract inpBuf inpBuf !pst
1384 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1386-- XXX return the remaining stream as part of the error.
1387-- XXX This is in fact parseMany1 (a la foldMany1). Do we need a parseMany as
1388-- well?
1389{-# INLINE_NORMAL parseManyD #-}
1390parseManyD
1391 :: Monad m
1392 => PRD.Parser a m b
1393 -> Stream m a
1394 -> Stream m (Either ParseError b)
1395parseManyD (PRD.Parser pstep initial extract) (Stream step state) =
1396 Stream stepOuter (ParseChunksInit [] state)
1398 where
1400 {-# INLINE_LATE stepOuter #-}
1401 -- Buffer is empty, get the first element from the stream, initialize the
1402 -- fold and then go to stream processing loop.
1403 stepOuter gst (ParseChunksInit [] st) = do
1404 r <- step (adaptState gst) st
1405 case r of
1406 Yield x s -> do
1407 res <- initial
1408 case res of
1409 PRD.IPartial ps ->
1410 return $ Skip $ ParseChunksBuf [x] s [] ps
1411 PRD.IDone pb ->
1412 let next = ParseChunksInit [x] s
1413 in return $ Skip $ ParseChunksYield (Right pb) next
1414 PRD.IError err ->
1415 return
1416 $ Skip
1417 $ ParseChunksYield
1418 (Left (ParseError err))
1419 (ParseChunksInitLeftOver [])
1420 Skip s -> return $ Skip $ ParseChunksInit [] s
1421 Stop -> return Stop
1423 -- Buffer is not empty, go to buffered processing loop
1424 stepOuter _ (ParseChunksInit src st) = do
1425 res <- initial
1426 case res of
1427 PRD.IPartial ps ->
1428 return $ Skip $ ParseChunksBuf src st [] ps
1429 PRD.IDone pb ->
1430 let next = ParseChunksInit src st
1431 in return $ Skip $ ParseChunksYield (Right pb) next
1432 PRD.IError err ->
1433 return
1434 $ Skip
1435 $ ParseChunksYield
1436 (Left (ParseError err))
1437 (ParseChunksInitLeftOver [])
1439 -- This is simplified ParseChunksInit
1440 stepOuter _ (ParseChunksInitBuf src) = do
1441 res <- initial
1442 case res of
1443 PRD.IPartial ps ->
1444 return $ Skip $ ParseChunksExtract src [] ps
1445 PRD.IDone pb ->
1446 let next = ParseChunksInitBuf src
1447 in return $ Skip $ ParseChunksYield (Right pb) next
1448 PRD.IError err ->
1449 return
1450 $ Skip
1451 $ ParseChunksYield
1452 (Left (ParseError err))
1453 (ParseChunksInitLeftOver [])
1455 -- XXX we just discard any leftover input at the end
1456 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1458 -- Buffer is empty, process elements from the stream
1459 stepOuter gst (ParseChunksStream st buf pst) = do
1460 r <- step (adaptState gst) st
1461 case r of
1462 Yield x s -> do
1463 pRes <- pstep pst x
1464 case pRes of
1465 PR.Partial 0 pst1 ->
1466 return $ Skip $ ParseChunksStream s [] pst1
1467 PR.Partial n pst1 -> do
1468 assert (n <= length (x:buf)) (return ())
1469 let src0 = Prelude.take n (x:buf)
1470 src = Prelude.reverse src0
1471 return $ Skip $ ParseChunksBuf src s [] pst1
1472 PR.Continue 0 pst1 ->
1473 return $ Skip $ ParseChunksStream s (x:buf) pst1
1474 PR.Continue n pst1 -> do
1475 assert (n <= length (x:buf)) (return ())
1476 let (src0, buf1) = splitAt n (x:buf)
1477 src = Prelude.reverse src0
1478 return $ Skip $ ParseChunksBuf src s buf1 pst1
1479 PR.Done 0 b -> do
1480 return $ Skip $
1481 ParseChunksYield (Right b) (ParseChunksInit [] s)
1482 PR.Done n b -> do
1483 assert (n <= length (x:buf)) (return ())
1484 let src = Prelude.reverse (Prelude.take n (x:buf))
1485 return $ Skip $
1486 ParseChunksYield (Right b) (ParseChunksInit src s)
1487 PR.Error err ->
1488 return
1489 $ Skip
1490 $ ParseChunksYield
1491 (Left (ParseError err))
1492 (ParseChunksInitLeftOver [])
1493 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1494 Stop -> return $ Skip $ ParseChunksStop buf pst
1496 -- go back to stream processing mode
1497 stepOuter _ (ParseChunksBuf [] s buf pst) =
1498 return $ Skip $ ParseChunksStream s buf pst
1500 -- buffered processing loop
1501 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1502 pRes <- pstep pst x
1503 case pRes of
1504 PR.Partial 0 pst1 ->
1505 return $ Skip $ ParseChunksBuf xs s [] pst1
1506 PR.Partial n pst1 -> do
1507 assert (n <= length (x:buf)) (return ())
1508 let src0 = Prelude.take n (x:buf)
1509 src = Prelude.reverse src0 ++ xs
1510 return $ Skip $ ParseChunksBuf src s [] pst1
1511 PR.Continue 0 pst1 ->
1512 return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1513 PR.Continue n pst1 -> do
1514 assert (n <= length (x:buf)) (return ())
1515 let (src0, buf1) = splitAt n (x:buf)
1516 src = Prelude.reverse src0 ++ xs
1517 return $ Skip $ ParseChunksBuf src s buf1 pst1
1518 PR.Done 0 b ->
1519 return
1520 $ Skip
1521 $ ParseChunksYield (Right b) (ParseChunksInit xs s)
1522 PR.Done n b -> do
1523 assert (n <= length (x:buf)) (return ())
1524 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1525 return $ Skip
1526 $ ParseChunksYield (Right b) (ParseChunksInit src s)
1527 PR.Error err ->
1528 return
1529 $ Skip
1530 $ ParseChunksYield
1531 (Left (ParseError err))
1532 (ParseChunksInitLeftOver [])
1534 -- This is simplified ParseChunksBuf
1535 stepOuter _ (ParseChunksExtract [] buf pst) =
1536 return $ Skip $ ParseChunksStop buf pst
1538 stepOuter _ (ParseChunksExtract (x:xs) buf pst) = do
1539 pRes <- pstep pst x
1540 case pRes of
1541 PR.Partial 0 pst1 ->
1542 return $ Skip $ ParseChunksExtract xs [] pst1
1543 PR.Partial n pst1 -> do
1544 assert (n <= length (x:buf)) (return ())
1545 let src0 = Prelude.take n (x:buf)
1546 src = Prelude.reverse src0 ++ xs
1547 return $ Skip $ ParseChunksExtract src [] pst1
1548 PR.Continue 0 pst1 ->
1549 return $ Skip $ ParseChunksExtract xs (x:buf) pst1
1550 PR.Continue n pst1 -> do
1551 assert (n <= length (x:buf)) (return ())
1552 let (src0, buf1) = splitAt n (x:buf)
1553 src = Prelude.reverse src0 ++ xs
1554 return $ Skip $ ParseChunksExtract src buf1 pst1
1555 PR.Done 0 b ->
1556 return
1557 $ Skip
1558 $ ParseChunksYield (Right b) (ParseChunksInitBuf xs)
1559 PR.Done n b -> do
1560 assert (n <= length (x:buf)) (return ())
1561 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1562 return
1563 $ Skip
1564 $ ParseChunksYield (Right b) (ParseChunksInitBuf src)
1565 PR.Error err ->
1566 return
1567 $ Skip
1568 $ ParseChunksYield
1569 (Left (ParseError err))
1570 (ParseChunksInitLeftOver [])
1572 -- This is simplified ParseChunksExtract
1573 stepOuter _ (ParseChunksStop buf pst) = do
1574 pRes <- extract pst
1575 case pRes of
1576 PR.Partial _ _ -> error "Bug: parseMany: Partial in extract"
1577 PR.Continue 0 pst1 ->
1578 return $ Skip $ ParseChunksStop buf pst1
1579 PR.Continue n pst1 -> do
1580 assert (n <= length buf) (return ())
1581 let (src0, buf1) = splitAt n buf
1582 src = Prelude.reverse src0
1583 return $ Skip $ ParseChunksExtract src buf1 pst1
1584 PR.Done 0 b -> do
1585 return $ Skip $
1586 ParseChunksYield (Right b) (ParseChunksInitLeftOver [])
1587 PR.Done n b -> do
1588 assert (n <= length buf) (return ())
1589 let src = Prelude.reverse (Prelude.take n buf)
1590 return $ Skip $
1591 ParseChunksYield (Right b) (ParseChunksInitBuf src)
1592 PR.Error err ->
1593 return
1594 $ Skip
1595 $ ParseChunksYield
1596 (Left (ParseError err))
1597 (ParseChunksInitLeftOver [])
1599 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1601-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
1602-- output stream.
1604-- Example:
1606-- >>> s = Stream.fromList [1..10]
1607-- >>> parser = Parser.takeBetween 0 2 Fold.sum
1608-- >>> Stream.fold Fold.toList $ Stream.parseMany parser s
1609-- [Right 3,Right 7,Right 11,Right 15,Right 19]
1611-- This is the streaming equivalent of the 'Streamly.Data.Parser.many' parse
1612-- combinator.
1614-- Known Issues: When the parser fails there is no way to get the remaining
1615-- stream.
1617{-# INLINE parseMany #-}
1618parseMany
1619 :: Monad m
1620 => PR.Parser a m b
1621 -> Stream m a
1622 -> Stream m (Either ParseError b)
1623parseMany = parseManyD
1625-- | Apply a stream of parsers to an input stream and emit the results in the
1626-- output stream.
1628-- /Unimplemented/
1630{-# INLINE parseSequence #-}
1631parseSequence
1632 :: -- Monad m =>
1633 Stream m (PR.Parser a m b)
1634 -> Stream m a
1635 -> Stream m b
1636parseSequence _f _m = undefined
1638-- XXX Change the parser arguments' order
1640-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
1641-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
1642-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
1643-- output of @test@ is discarded and the output of @collect@ is emitted in the
1644-- output stream. The parser fails if @collect@ fails.
1646-- /Unimplemented/
1648{-# INLINE parseManyTill #-}
1649parseManyTill ::
1650 -- MonadThrow m =>
1651 PR.Parser a m b
1652 -> PR.Parser a m x
1653 -> Stream m a
1654 -> Stream m b
1655parseManyTill = undefined
1657{-# ANN type ConcatParseState Fuse #-}
1658data ConcatParseState c b inpBuf st p m a =
1659 ConcatParseInit inpBuf st p
1660 | ConcatParseInitBuf inpBuf p
1661 | ConcatParseInitLeftOver inpBuf
1662 | forall s. ConcatParseStop
1663 inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1664 | forall s. ConcatParseStream
1665 st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1666 | forall s. ConcatParseBuf
1667 inpBuf st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1668 | forall s. ConcatParseExtract
1669 inpBuf inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1670 | ConcatParseYield c (ConcatParseState c b inpBuf st p m a)
1672-- XXX Review the changes
1673{-# INLINE_NORMAL parseIterateD #-}
1674parseIterateD
1675 :: Monad m
1676 => (b -> PRD.Parser a m b)
1677 -> b
1678 -> Stream m a
1679 -> Stream m (Either ParseError b)
1680parseIterateD func seed (Stream step state) =
1681 Stream stepOuter (ConcatParseInit [] state (func seed))
1683 where
1685 {-# INLINE_LATE stepOuter #-}
1686 -- Buffer is empty, go to stream processing loop
1687 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1688 res <- initial
1689 case res of
1690 PRD.IPartial ps ->
1691 return $ Skip $ ConcatParseStream st [] pstep ps extract
1692 PRD.IDone pb ->
1693 let next = ConcatParseInit [] st (func pb)
1694 in return $ Skip $ ConcatParseYield (Right pb) next
1695 PRD.IError err ->
1696 return
1697 $ Skip
1698 $ ConcatParseYield
1699 (Left (ParseError err))
1700 (ConcatParseInitLeftOver [])
1702 -- Buffer is not empty, go to buffered processing loop
1703 stepOuter _ (ConcatParseInit src st
1704 (PRD.Parser pstep initial extract)) = do
1705 res <- initial
1706 case res of
1707 PRD.IPartial ps ->
1708 return $ Skip $ ConcatParseBuf src st [] pstep ps extract
1709 PRD.IDone pb ->
1710 let next = ConcatParseInit src st (func pb)
1711 in return $ Skip $ ConcatParseYield (Right pb) next
1712 PRD.IError err ->
1713 return
1714 $ Skip
1715 $ ConcatParseYield
1716 (Left (ParseError err))
1717 (ConcatParseInitLeftOver [])
1719 -- This is simplified ConcatParseInit
1720 stepOuter _ (ConcatParseInitBuf src
1721 (PRD.Parser pstep initial extract)) = do
1722 res <- initial
1723 case res of
1724 PRD.IPartial ps ->
1725 return $ Skip $ ConcatParseExtract src [] pstep ps extract
1726 PRD.IDone pb ->
1727 let next = ConcatParseInitBuf src (func pb)
1728 in return $ Skip $ ConcatParseYield (Right pb) next
1729 PRD.IError err ->
1730 return
1731 $ Skip
1732 $ ConcatParseYield
1733 (Left (ParseError err))
1734 (ConcatParseInitLeftOver [])
1736 -- XXX we just discard any leftover input at the end
1737 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1739 -- Buffer is empty process elements from the stream
1740 stepOuter gst (ConcatParseStream st buf pstep pst extract) = do
1741 r <- step (adaptState gst) st
1742 case r of
1743 Yield x s -> do
1744 pRes <- pstep pst x
1745 case pRes of
1746 PR.Partial 0 pst1 ->
1747 return $ Skip $ ConcatParseStream s [] pstep pst1 extract
1748 PR.Partial n pst1 -> do
1749 assert (n <= length (x:buf)) (return ())
1750 let src0 = Prelude.take n (x:buf)
1751 src = Prelude.reverse src0
1752 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1753 -- PR.Continue 0 pst1 ->
1754 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1755 PR.Continue n pst1 -> do
1756 assert (n <= length (x:buf)) (return ())
1757 let (src0, buf1) = splitAt n (x:buf)
1758 src = Prelude.reverse src0
1759 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1760 -- XXX Specialize for Stop 0 common case?
1761 PR.Done n b -> do
1762 assert (n <= length (x:buf)) (return ())
1763 let src = Prelude.reverse (Prelude.take n (x:buf))
1764 return $ Skip $
1765 ConcatParseYield (Right b) (ConcatParseInit src s (func b))
1766 PR.Error err ->
1767 return
1768 $ Skip
1769 $ ConcatParseYield
1770 (Left (ParseError err))
1771 (ConcatParseInitLeftOver [])
1772 Skip s -> return $ Skip $ ConcatParseStream s buf pstep pst extract
1773 Stop -> return $ Skip $ ConcatParseStop buf pstep pst extract
1775 -- go back to stream processing mode
1776 stepOuter _ (ConcatParseBuf [] s buf pstep ps extract) =
1777 return $ Skip $ ConcatParseStream s buf pstep ps extract
1779 -- buffered processing loop
1780 stepOuter _ (ConcatParseBuf (x:xs) s buf pstep pst extract) = do
1781 pRes <- pstep pst x
1782 case pRes of
1783 PR.Partial 0 pst1 ->
1784 return $ Skip $ ConcatParseBuf xs s [] pstep pst1 extract
1785 PR.Partial n pst1 -> do
1786 assert (n <= length (x:buf)) (return ())
1787 let src0 = Prelude.take n (x:buf)
1788 src = Prelude.reverse src0 ++ xs
1789 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1790 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1791 PR.Continue n pst1 -> do
1792 assert (n <= length (x:buf)) (return ())
1793 let (src0, buf1) = splitAt n (x:buf)
1794 src = Prelude.reverse src0 ++ xs
1795 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1796 -- XXX Specialize for Stop 0 common case?
1797 PR.Done n b -> do
1798 assert (n <= length (x:buf)) (return ())
1799 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1800 return $ Skip $ ConcatParseYield (Right b)
1801 (ConcatParseInit src s (func b))
1802 PR.Error err ->
1803 return
1804 $ Skip
1805 $ ConcatParseYield
1806 (Left (ParseError err))
1807 (ConcatParseInitLeftOver [])
1809 -- This is simplified ConcatParseBuf
1810 stepOuter _ (ConcatParseExtract [] buf pstep pst extract) =
1811 return $ Skip $ ConcatParseStop buf pstep pst extract
1813 stepOuter _ (ConcatParseExtract (x:xs) buf pstep pst extract) = do
1814 pRes <- pstep pst x
1815 case pRes of
1816 PR.Partial 0 pst1 ->
1817 return $ Skip $ ConcatParseExtract xs [] pstep pst1 extract
1818 PR.Partial n pst1 -> do
1819 assert (n <= length (x:buf)) (return ())
1820 let src0 = Prelude.take n (x:buf)
1821 src = Prelude.reverse src0 ++ xs
1822 return $ Skip $ ConcatParseExtract src [] pstep pst1 extract
1823 PR.Continue 0 pst1 ->
1824 return $ Skip $ ConcatParseExtract xs (x:buf) pstep pst1 extract
1825 PR.Continue n pst1 -> do
1826 assert (n <= length (x:buf)) (return ())
1827 let (src0, buf1) = splitAt n (x:buf)
1828 src = Prelude.reverse src0 ++ xs
1829 return $ Skip $ ConcatParseExtract src buf1 pstep pst1 extract
1830 PR.Done 0 b ->
1831 return $ Skip $ ConcatParseYield (Right b) (ConcatParseInitBuf xs (func b))
1832 PR.Done n b -> do
1833 assert (n <= length (x:buf)) (return ())
1834 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1835 return $ Skip $ ConcatParseYield (Right b) (ConcatParseInitBuf src (func b))
1836 PR.Error err ->
1837 return
1838 $ Skip
1839 $ ConcatParseYield
1840 (Left (ParseError err))
1841 (ConcatParseInitLeftOver [])
1843 -- This is simplified ConcatParseExtract
1844 stepOuter _ (ConcatParseStop buf pstep pst extract) = do
1845 pRes <- extract pst
1846 case pRes of
1847 PR.Partial _ _ -> error "Bug: parseIterate: Partial in extract"
1848 PR.Continue 0 pst1 ->
1849 return $ Skip $ ConcatParseStop buf pstep pst1 extract
1850 PR.Continue n pst1 -> do
1851 assert (n <= length buf) (return ())
1852 let (src0, buf1) = splitAt n buf
1853 src = Prelude.reverse src0
1854 return $ Skip $ ConcatParseExtract src buf1 pstep pst1 extract
1855 PR.Done 0 b -> do
1856 return $ Skip $
1857 ConcatParseYield (Right b) (ConcatParseInitLeftOver [])
1858 PR.Done n b -> do
1859 assert (n <= length buf) (return ())
1860 let src = Prelude.reverse (Prelude.take n buf)
1861 return $ Skip $
1862 ConcatParseYield (Right b) (ConcatParseInitBuf src (func b))
1863 PR.Error err ->
1864 return
1865 $ Skip
1866 $ ConcatParseYield
1867 (Left (ParseError err))
1868 (ConcatParseInitLeftOver [])
1870 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1872-- | Iterate a parser generating function on a stream. The initial value @b@ is
1873-- used to generate the first parser, the parser is applied on the stream and
1874-- the result is used to generate the next parser and so on.
1876-- >>> import Data.Monoid (Sum(..))
1877-- >>> s = Stream.fromList [1..10]
1878-- >>> Stream.fold Fold.toList $ fmap getSum $ Stream.catRights $ Stream.parseIterate (\b -> Parser.takeBetween 0 2 (Fold.sconcat b)) (Sum 0) $ fmap Sum s
1879-- [3,10,21,36,55,55]
1881-- This is the streaming equivalent of monad like sequenced application of
1882-- parsers where next parser is dependent on the previous parser.
1884-- /Pre-release/
1886{-# INLINE parseIterate #-}
1887parseIterate
1888 :: Monad m
1889 => (b -> PR.Parser a m b)
1890 -> b
1891 -> Stream m a
1892 -> Stream m (Either ParseError b)
1893parseIterate = parseIterateD
1895------------------------------------------------------------------------------
1896-- Grouping
1897------------------------------------------------------------------------------
1899data GroupByState st fs a b
1900 = GroupingInit st
1901 | GroupingDo st !fs
1902 | GroupingInitWith st !a
1903 | GroupingDoWith st !fs !a
1904 | GroupingYield !b (GroupByState st fs a b)
1905 | GroupingDone
1907{-# INLINE_NORMAL groupsBy #-}
1908groupsBy :: Monad m
1909 => (a -> a -> Bool)
1910 -> Fold m a b
1911 -> Stream m a
1912 -> Stream m b
1914groupsBy eq fld = parseMany (PRD.groupBy eq fld)
1916groupsBy cmp (Fold fstep initial done) (Stream step state) =
1917 Stream stepOuter (GroupingInit state)
1919 where
1921 {-# INLINE_LATE stepOuter #-}
1922 stepOuter _ (GroupingInit st) = do
1923 -- XXX Note that if the stream stops without yielding a single element
1924 -- in the group we discard the "initial" effect.
1925 res <- initial
1926 return
1927 $ case res of
1928 FL.Partial s -> Skip $ GroupingDo st s
1929 FL.Done b -> Yield b $ GroupingInit st
1930 stepOuter gst (GroupingDo st fs) = do
1931 res <- step (adaptState gst) st
1932 case res of
1933 Yield x s -> do
1934 r <- fstep fs x
1935 case r of
1936 FL.Partial fs1 -> go SPEC x s fs1
1937 FL.Done b -> return $ Yield b (GroupingInit s)
1938 Skip s -> return $ Skip $ GroupingDo s fs
1939 Stop -> return Stop
1941 where
1943 go !_ prev stt !acc = do
1944 res <- step (adaptState gst) stt
1945 case res of
1946 Yield x s -> do
1947 if cmp x prev
1948 then do
1949 r <- fstep acc x
1950 case r of
1951 FL.Partial fs1 -> go SPEC prev s fs1
1952 FL.Done b -> return $ Yield b (GroupingInit s)
1953 else do
1954 r <- done acc
1955 return $ Yield r (GroupingInitWith s x)
1956 Skip s -> go SPEC prev s acc
1957 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1958 stepOuter _ (GroupingInitWith st x) = do
1959 res <- initial
1960 return
1961 $ case res of
1962 FL.Partial s -> Skip $ GroupingDoWith st s x
1963 FL.Done b -> Yield b $ GroupingInitWith st x
1964 stepOuter gst (GroupingDoWith st fs prev) = do
1965 res <- fstep fs prev
1966 case res of
1967 FL.Partial fs1 -> go SPEC st fs1
1968 FL.Done b -> return $ Yield b (GroupingInit st)
1970 where
1972 -- XXX code duplicated from the previous equation
1973 go !_ stt !acc = do
1974 res <- step (adaptState gst) stt
1975 case res of
1976 Yield x s -> do
1977 if cmp x prev
1978 then do
1979 r <- fstep acc x
1980 case r of
1981 FL.Partial fs1 -> go SPEC s fs1
1982 FL.Done b -> return $ Yield b (GroupingInit s)
1983 else do
1984 r <- done acc
1985 return $ Yield r (GroupingInitWith s x)
1986 Skip s -> go SPEC s acc
1987 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1988 stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1989 stepOuter _ GroupingDone = return Stop
1991{-# INLINE_NORMAL groupsRollingBy #-}
1992groupsRollingBy :: Monad m
1993 => (a -> a -> Bool)
1994 -> Fold m a b
1995 -> Stream m a
1996 -> Stream m b
1998groupsRollingBy eq fld = parseMany (PRD.groupByRolling eq fld)
2000groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
2001 Stream stepOuter (GroupingInit state)
2003 where
2005 {-# INLINE_LATE stepOuter #-}
2006 stepOuter _ (GroupingInit st) = do
2007 -- XXX Note that if the stream stops without yielding a single element
2008 -- in the group we discard the "initial" effect.
2009 res <- initial
2010 return
2011 $ case res of
2012 FL.Partial fs -> Skip $ GroupingDo st fs
2013 FL.Done fb -> Yield fb $ GroupingInit st
2014 stepOuter gst (GroupingDo st fs) = do
2015 res <- step (adaptState gst) st
2016 case res of
2017 Yield x s -> do
2018 r <- fstep fs x
2019 case r of
2020 FL.Partial fs1 -> go SPEC x s fs1
2021 FL.Done fb -> return $ Yield fb (GroupingInit s)
2022 Skip s -> return $ Skip $ GroupingDo s fs
2023 Stop -> return Stop
2025 where
2027 go !_ prev stt !acc = do
2028 res <- step (adaptState gst) stt
2029 case res of
2030 Yield x s -> do
2031 if cmp prev x
2032 then do
2033 r <- fstep acc x
2034 case r of
2035 FL.Partial fs1 -> go SPEC x s fs1
2036 FL.Done b -> return $ Yield b (GroupingInit s)
2037 else do
2038 r <- done acc
2039 return $ Yield r (GroupingInitWith s x)
2040 Skip s -> go SPEC prev s acc
2041 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
2042 stepOuter _ (GroupingInitWith st x) = do
2043 res <- initial
2044 return
2045 $ case res of
2046 FL.Partial s -> Skip $ GroupingDoWith st s x
2047 FL.Done b -> Yield b $ GroupingInitWith st x
2048 stepOuter gst (GroupingDoWith st fs previous) = do
2049 res <- fstep fs previous
2050 case res of
2051 FL.Partial s -> go SPEC previous st s
2052 FL.Done b -> return $ Yield b (GroupingInit st)
2054 where
2056 -- XXX GHC: groupsBy has one less parameter in this go loop and it
2057 -- fuses. However, groupsRollingBy does not fuse, removing the prev
2058 -- parameter makes it fuse. Something needs to be fixed in GHC. The
2059 -- workaround for this is noted in the comments below.
2060 go !_ prev !stt !acc = do
2061 res <- step (adaptState gst) stt
2062 case res of
2063 Yield x s -> do
2064 if cmp prev x
2065 then do
2066 r <- fstep acc x
2067 case r of
2068 FL.Partial fs1 -> go SPEC x s fs1
2069 FL.Done b -> return $ Yield b (GroupingInit st)
2070 else do
2071 {-
2072 r <- done acc
2073 return $ Yield r (GroupingInitWith s x)
2074 -}
2075 -- The code above does not let groupBy fuse. We use the
2076 -- alternative code below instead. Instead of jumping
2077 -- to GroupingInitWith state, we unroll the code of
2078 -- GroupingInitWith state here to help GHC with stream
2079 -- fusion.
2080 result <- initial
2081 r <- done acc
2082 return
2083 $ Yield r
2084 $ case result of
2085 FL.Partial fsi -> GroupingDoWith s fsi x
2086 FL.Done b -> GroupingYield b (GroupingInit s)
2087 Skip s -> go SPEC prev s acc
2088 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
2089 stepOuter _ (GroupingYield r next) = return $ Yield r next
2090 stepOuter _ GroupingDone = return Stop
2092------------------------------------------------------------------------------
2093-- Splitting - by a predicate
2094------------------------------------------------------------------------------
2096data WordsByState st fs b
2097 = WordsByInit st
2098 | WordsByDo st !fs
2099 | WordsByDone
2100 | WordsByYield !b (WordsByState st fs b)
2102{-# INLINE_NORMAL wordsBy #-}
2103wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
2104wordsBy predicate (Fold fstep initial done) (Stream step state) =
2105 Stream stepOuter (WordsByInit state)
2107 where
2109 {-# INLINE_LATE stepOuter #-}
2110 stepOuter _ (WordsByInit st) = do
2111 res <- initial
2112 return
2113 $ case res of
2114 FL.Partial s -> Skip $ WordsByDo st s
2115 FL.Done b -> Yield b (WordsByInit st)
2117 stepOuter gst (WordsByDo st fs) = do
2118 res <- step (adaptState gst) st
2119 case res of
2120 Yield x s -> do
2121 if predicate x
2122 then do
2123 resi <- initial
2124 return
2125 $ case resi of
2126 FL.Partial fs1 -> Skip $ WordsByDo s fs1
2127 FL.Done b -> Yield b (WordsByInit s)
2128 else do
2129 r <- fstep fs x
2130 case r of
2131 FL.Partial fs1 -> go SPEC s fs1
2132 FL.Done b -> return $ Yield b (WordsByInit s)
2133 Skip s -> return $ Skip $ WordsByDo s fs
2134 Stop -> return Stop
2136 where
2138 go !_ stt !acc = do
2139 res <- step (adaptState gst) stt
2140 case res of
2141 Yield x s -> do
2142 if predicate x
2143 then do
2144 {-
2145 r <- done acc
2146 return $ Yield r (WordsByInit s)
2147 -}
2148 -- The above code does not fuse well. Need to check why
2149 -- GHC is not able to simplify it well. Using the code
2150 -- below, instead of jumping through the WordsByInit
2151 -- state always, we directly go to WordsByDo state in
2152 -- the common case of Partial.
2153 resi <- initial
2154 r <- done acc
2155 return
2156 $ Yield r
2157 $ case resi of
2158 FL.Partial fs1 -> WordsByDo s fs1
2159 FL.Done b -> WordsByYield b (WordsByInit s)
2160 else do
2161 r <- fstep acc x
2162 case r of
2163 FL.Partial fs1 -> go SPEC s fs1
2164 FL.Done b -> return $ Yield b (WordsByInit s)
2165 Skip s -> go SPEC s acc
2166 Stop -> done acc >>= \r -> return $ Yield r WordsByDone
2168 stepOuter _ WordsByDone = return Stop
2170 stepOuter _ (WordsByYield b next) = return $ Yield b next
2172------------------------------------------------------------------------------
2173-- Splitting on a sequence
2174------------------------------------------------------------------------------
2176-- String search algorithms:
2177-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
2180-- TODO can we unify the splitting operations using a splitting configuration
2181-- like in the split package.
2183data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
2184data SplitOptions = SplitOptions
2185 { style :: SplitStyle
2186 , withSep :: Bool -- ^ keep the separators in output
2187 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
2188 -- , trimHead :: Bool -- ^ drop blank at head
2189 -- , trimTail :: Bool -- ^ drop blank at tail
2193-- XXX using "fs" as the last arg in Constructors may simplify the code a bit,
2194-- because we can use the constructor directly without having to create "jump"
2195-- functions.
2196{-# ANN type SplitOnSeqState Fuse #-}
2197data SplitOnSeqState rb rh ck w fs s b x =
2198 SplitOnSeqInit
2199 | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
2200 | SplitOnSeqDone
2202 | SplitOnSeqEmpty !fs s
2204 | SplitOnSeqSingle !fs s x
2206 | SplitOnSeqWordInit !fs s
2207 | SplitOnSeqWordLoop !w s !fs
2208 | SplitOnSeqWordDone Int !fs !w
2210 | SplitOnSeqKRInit Int !fs s rb !rh
2211 | SplitOnSeqKRLoop fs s rb !rh !ck
2212 | SplitOnSeqKRCheck fs s rb !rh
2213 | SplitOnSeqKRDone Int !fs rb !rh
2215 | SplitOnSeqReinit (fs -> SplitOnSeqState rb rh ck w fs s b x)
2217{-# INLINE_NORMAL splitOnSeq #-}
2218splitOnSeq
2219 :: forall m a b. (MonadIO m, Storable a, Unbox a, Enum a, Eq a)
2220 => Array a
2221 -> Fold m a b
2222 -> Stream m a
2223 -> Stream m b
2224splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
2225 Stream stepOuter SplitOnSeqInit
2227 where
2229 patLen = A.length patArr
2230 maxIndex = patLen - 1
2231 elemBits = SIZE_OF(a) * 8
2233 -- For word pattern case
2234 wordMask :: Word
2235 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
2237 elemMask :: Word
2238 elemMask = (1 `shiftL` elemBits) - 1
2240 wordPat :: Word
2241 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2243 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2245 -- For Rabin-Karp search
2246 k = 2891336453 :: Word32
2247 coeff = k ^ patLen
2249 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2251 deltaCksum cksum old new =
2252 addCksum cksum new - coeff * fromIntegral (fromEnum old)
2254 -- XXX shall we use a random starting hash or 1 instead of 0?
2255 patHash = A.foldl' addCksum 0 patArr
2257 skip = return . Skip
2259 nextAfterInit nextGen stepRes =
2260 case stepRes of
2261 FL.Partial s -> nextGen s
2262 FL.Done b -> SplitOnSeqYield b (SplitOnSeqReinit nextGen)
2264 {-# INLINE yieldProceed #-}
2265 yieldProceed nextGen fs =
2266 initial >>= skip . SplitOnSeqYield fs . nextAfterInit nextGen
2268 {-# INLINE_LATE stepOuter #-}
2269 stepOuter _ SplitOnSeqInit = do
2270 res <- initial
2271 case res of
2272 FL.Partial acc ->
2273 if patLen == 0
2274 then return $ Skip $ SplitOnSeqEmpty acc state
2275 else if patLen == 1
2276 then do
2277 pat <- liftIO $ A.unsafeIndexIO 0 patArr
2278 return $ Skip $ SplitOnSeqSingle acc state pat
2279 else if SIZE_OF(a) * patLen
2280 <= sizeOf (Proxy :: Proxy Word)
2281 then return $ Skip $ SplitOnSeqWordInit acc state
2282 else do
2283 (rb, rhead) <- liftIO $ RB.new patLen
2284 skip $ SplitOnSeqKRInit 0 acc state rb rhead
2285 FL.Done b -> skip $ SplitOnSeqYield b SplitOnSeqInit
2287 stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
2289 ---------------------------
2290 -- Checkpoint
2291 ---------------------------
2293 stepOuter _ (SplitOnSeqReinit nextGen) =
2294 initial >>= skip . nextAfterInit nextGen
2296 ---------------------------
2297 -- Empty pattern
2298 ---------------------------
2300 stepOuter gst (SplitOnSeqEmpty acc st) = do
2301 res <- step (adaptState gst) st
2302 case res of
2303 Yield x s -> do
2304 r <- fstep acc x
2305 b1 <-
2306 case r of
2307 FL.Partial acc1 -> done acc1
2308 FL.Done b -> return b
2309 let jump c = SplitOnSeqEmpty c s
2310 in yieldProceed jump b1
2311 Skip s -> skip (SplitOnSeqEmpty acc s)
2312 Stop -> return Stop
2314 -----------------
2315 -- Done
2316 -----------------
2318 stepOuter _ SplitOnSeqDone = return Stop
2320 -----------------
2321 -- Single Pattern
2322 -----------------
2324 stepOuter gst (SplitOnSeqSingle fs st pat) = do
2325 res <- step (adaptState gst) st
2326 case res of
2327 Yield x s -> do
2328 let jump c = SplitOnSeqSingle c s pat
2329 if pat == x
2330 then done fs >>= yieldProceed jump
2331 else do
2332 r <- fstep fs x
2333 case r of
2334 FL.Partial fs1 -> skip $ jump fs1
2335 FL.Done b -> yieldProceed jump b
2336 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
2337 Stop -> do
2338 r <- done fs
2339 return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
2341 ---------------------------
2342 -- Short Pattern - Shift Or
2343 ---------------------------
2345 stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
2346 r <- done fs
2347 skip $ SplitOnSeqYield r SplitOnSeqDone
2348 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
2349 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2350 r <- fstep fs (toEnum $ fromIntegral old)
2351 case r of
2352 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
2353 FL.Done b -> do
2354 let jump c = SplitOnSeqWordDone (n - 1) c wrd
2355 yieldProceed jump b
2357 stepOuter gst (SplitOnSeqWordInit fs st0) =
2358 go SPEC 0 0 st0
2360 where
2362 {-# INLINE go #-}
2363 go !_ !idx !wrd !st = do
2364 res <- step (adaptState gst) st
2365 case res of
2366 Yield x s -> do
2367 let wrd1 = addToWord wrd x
2368 if idx == maxIndex
2369 then do
2370 if wrd1 .&. wordMask == wordPat
2371 then do
2372 let jump c = SplitOnSeqWordInit c s
2373 done fs >>= yieldProceed jump
2374 else skip $ SplitOnSeqWordLoop wrd1 s fs
2375 else go SPEC (idx + 1) wrd1 s
2376 Skip s -> go SPEC idx wrd s
2377 Stop -> do
2378 if idx /= 0
2379 then skip $ SplitOnSeqWordDone idx fs wrd
2380 else do
2381 r <- done fs
2382 skip $ SplitOnSeqYield r SplitOnSeqDone
2384 stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
2385 go SPEC wrd0 st0 fs0
2387 where
2389 {-# INLINE go #-}
2390 go !_ !wrd !st !fs = do
2391 res <- step (adaptState gst) st
2392 case res of
2393 Yield x s -> do
2394 let jump c = SplitOnSeqWordInit c s
2395 wrd1 = addToWord wrd x
2396 old = (wordMask .&. wrd)
2397 `shiftR` (elemBits * (patLen - 1))
2398 r <- fstep fs (toEnum $ fromIntegral old)
2399 case r of
2400 FL.Partial fs1 -> do
2401 if wrd1 .&. wordMask == wordPat
2402 then done fs1 >>= yieldProceed jump
2403 else go SPEC wrd1 s fs1
2404 FL.Done b -> yieldProceed jump b
2405 Skip s -> go SPEC wrd s fs
2406 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
2408 -------------------------------
2409 -- General Pattern - Karp Rabin
2410 -------------------------------
2412 stepOuter gst (SplitOnSeqKRInit idx fs st rb rh) = do
2413 res <- step (adaptState gst) st
2414 case res of
2415 Yield x s -> do
2416 rh1 <- liftIO $ RB.unsafeInsert rb rh x
2417 if idx == maxIndex
2418 then do
2419 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2420 let !ringHash = fld addCksum 0 rb
2421 if ringHash == patHash
2422 then skip $ SplitOnSeqKRCheck fs s rb rh1
2423 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
2424 else skip $ SplitOnSeqKRInit (idx + 1) fs s rb rh1
2425 Skip s -> skip $ SplitOnSeqKRInit idx fs s rb rh
2426 Stop -> do
2427 skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
2429 -- XXX The recursive "go" is more efficient than the state based recursion
2430 -- code commented out below. Perhaps its more efficient because of
2431 -- factoring out "rb" outside the loop.
2432 --
2433 stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
2434 go SPEC fs0 st0 rh0 cksum0
2436 where
2438 go !_ !fs !st !rh !cksum = do
2439 res <- step (adaptState gst) st
2440 case res of
2441 Yield x s -> do
2442 old <- liftIO $ peek rh
2443 let cksum1 = deltaCksum cksum old x
2444 r <- fstep fs old
2445 case r of
2446 FL.Partial fs1 -> do
2447 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2448 if cksum1 == patHash
2449 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
2450 else go SPEC fs1 s rh1 cksum1
2451 FL.Done b -> do
2452 let rst = RB.startOf rb
2453 jump c = SplitOnSeqKRInit 0 c s rb rst
2454 yieldProceed jump b
2455 Skip s -> go SPEC fs s rh cksum
2456 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
2458 -- XXX The following code is 5 times slower compared to the recursive loop
2459 -- based code above. Need to investigate why. One possibility is that the
2460 -- go loop above does not thread around the ring buffer (rb). This code may
2461 -- be causing the state to bloat and getting allocated on each iteration.
2462 -- We can check the cmm/asm code to confirm. If so a good GHC solution to
2463 -- such problem is needed. One way to avoid this could be to use unboxed
2464 -- mutable state?
2465 {-
2466 stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
2467 res <- step (adaptState gst) st
2468 case res of
2469 Yield x s -> do
2470 old <- liftIO $ peek rh
2471 let cksum1 = deltaCksum cksum old x
2472 fs1 <- fstep fs old
2473 if (cksum1 == patHash)
2474 then do
2475 r <- done fs1
2476 skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
2477 else do
2478 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2479 skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
2480 Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
2481 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
2482 -}
2484 stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
2485 if RB.unsafeEqArray rb rh patArr
2486 then do
2487 r <- done fs
2488 let rst = RB.startOf rb
2489 jump c = SplitOnSeqKRInit 0 c st rb rst
2490 yieldProceed jump r
2491 else skip $ SplitOnSeqKRLoop fs st rb rh patHash
2493 stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
2494 r <- done fs
2495 skip $ SplitOnSeqYield r SplitOnSeqDone
2496 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
2497 old <- liftIO $ peek rh
2498 let rh1 = RB.advance rb rh
2499 r <- fstep fs old
2500 case r of
2501 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
2502 FL.Done b -> do
2503 let jump c = SplitOnSeqKRDone (n - 1) c rb rh1
2504 yieldProceed jump b
2506{-# ANN type SplitOnSuffixSeqState Fuse #-}
2507data SplitOnSuffixSeqState rb rh ck w fs s b x =
2508 SplitOnSuffixSeqInit
2509 | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
2510 | SplitOnSuffixSeqDone
2512 | SplitOnSuffixSeqEmpty !fs s
2514 | SplitOnSuffixSeqSingleInit !fs s x
2515 | SplitOnSuffixSeqSingle !fs s x
2517 | SplitOnSuffixSeqWordInit !fs s
2518 | SplitOnSuffixSeqWordLoop !w s !fs
2519 | SplitOnSuffixSeqWordDone Int !fs !w
2521 | SplitOnSuffixSeqKRInit Int !fs s rb !rh
2522 | SplitOnSuffixSeqKRInit1 !fs s rb !rh
2523 | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
2524 | SplitOnSuffixSeqKRCheck fs s rb !rh
2525 | SplitOnSuffixSeqKRDone Int !fs rb !rh
2527 | SplitOnSuffixSeqReinit
2528 (fs -> SplitOnSuffixSeqState rb rh ck w fs s b x)
2530{-# INLINE_NORMAL splitOnSuffixSeq #-}
2531splitOnSuffixSeq
2532 :: forall m a b. (MonadIO m, Storable a, Unbox a, Enum a, Eq a)
2533 => Bool
2534 -> Array a
2535 -> Fold m a b
2536 -> Stream m a
2537 -> Stream m b
2538splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2539 Stream stepOuter SplitOnSuffixSeqInit
2541 where
2543 patLen = A.length patArr
2544 maxIndex = patLen - 1
2545 elemBits = SIZE_OF(a) * 8
2547 -- For word pattern case
2548 wordMask :: Word
2549 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
2551 elemMask :: Word
2552 elemMask = (1 `shiftL` elemBits) - 1
2554 wordPat :: Word
2555 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2557 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2559 nextAfterInit nextGen stepRes =
2560 case stepRes of
2561 FL.Partial s -> nextGen s
2562 FL.Done b ->
2563 SplitOnSuffixSeqYield b (SplitOnSuffixSeqReinit nextGen)
2565 {-# INLINE yieldProceed #-}
2566 yieldProceed nextGen fs =
2567 initial >>= skip . SplitOnSuffixSeqYield fs . nextAfterInit nextGen
2569 -- For single element pattern case
2570 {-# INLINE processYieldSingle #-}
2571 processYieldSingle pat x s fs = do
2572 let jump c = SplitOnSuffixSeqSingleInit c s pat
2573 if pat == x
2574 then do
2575 r <- if withSep then fstep fs x else return $ FL.Partial fs
2576 b1 <-
2577 case r of
2578 FL.Partial fs1 -> done fs1
2579 FL.Done b -> return b
2580 yieldProceed jump b1
2581 else do
2582 r <- fstep fs x
2583 case r of
2584 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2585 FL.Done b -> yieldProceed jump b
2587 -- For Rabin-Karp search
2588 k = 2891336453 :: Word32
2589 coeff = k ^ patLen
2591 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2593 deltaCksum cksum old new =
2594 addCksum cksum new - coeff * fromIntegral (fromEnum old)
2596 -- XXX shall we use a random starting hash or 1 instead of 0?
2597 patHash = A.foldl' addCksum 0 patArr
2599 skip = return . Skip
2601 {-# INLINE_LATE stepOuter #-}
2602 stepOuter _ SplitOnSuffixSeqInit = do
2603 res <- initial
2604 case res of
2605 FL.Partial fs ->
2606 if patLen == 0
2607 then skip $ SplitOnSuffixSeqEmpty fs state
2608 else if patLen == 1
2609 then do
2610 pat <- liftIO $ A.unsafeIndexIO 0 patArr
2611 skip $ SplitOnSuffixSeqSingleInit fs state pat
2612 else if SIZE_OF(a) * patLen
2613 <= sizeOf (Proxy :: Proxy Word)
2614 then skip $ SplitOnSuffixSeqWordInit fs state
2615 else do
2616 (rb, rhead) <- liftIO $ RB.new patLen
2617 skip $ SplitOnSuffixSeqKRInit 0 fs state rb rhead
2618 FL.Done fb -> skip $ SplitOnSuffixSeqYield fb SplitOnSuffixSeqInit
2620 stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
2622 ---------------------------
2623 -- Reinit
2624 ---------------------------
2626 stepOuter _ (SplitOnSuffixSeqReinit nextGen) =
2627 initial >>= skip . nextAfterInit nextGen
2629 ---------------------------
2630 -- Empty pattern
2631 ---------------------------
2633 stepOuter gst (SplitOnSuffixSeqEmpty acc st) = do
2634 res <- step (adaptState gst) st
2635 case res of
2636 Yield x s -> do
2637 let jump c = SplitOnSuffixSeqEmpty c s
2638 r <- fstep acc x
2639 b1 <-
2640 case r of
2641 FL.Partial fs -> done fs
2642 FL.Done b -> return b
2643 yieldProceed jump b1
2644 Skip s -> skip (SplitOnSuffixSeqEmpty acc s)
2645 Stop -> return Stop
2647 -----------------
2648 -- Done
2649 -----------------
2651 stepOuter _ SplitOnSuffixSeqDone = return Stop
2653 -----------------
2654 -- Single Pattern
2655 -----------------
2657 stepOuter gst (SplitOnSuffixSeqSingleInit fs st pat) = do
2658 res <- step (adaptState gst) st
2659 case res of
2660 Yield x s -> processYieldSingle pat x s fs
2661 Skip s -> skip $ SplitOnSuffixSeqSingleInit fs s pat
2662 Stop -> return Stop
2664 stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
2665 res <- step (adaptState gst) st
2666 case res of
2667 Yield x s -> processYieldSingle pat x s fs
2668 Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
2669 Stop -> do
2670 r <- done fs
2671 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2673 ---------------------------
2674 -- Short Pattern - Shift Or
2675 ---------------------------
2677 stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
2678 r <- done fs
2679 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2680 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2681 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2682 r <- fstep fs (toEnum $ fromIntegral old)
2683 case r of
2684 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2685 FL.Done b -> do
2686 let jump c = SplitOnSuffixSeqWordDone (n - 1) c wrd
2687 yieldProceed jump b
2689 stepOuter gst (SplitOnSuffixSeqWordInit fs0 st0) = do
2690 res <- step (adaptState gst) st0
2691 case res of
2692 Yield x s -> do
2693 let wrd = addToWord 0 x
2694 r <- if withSep then fstep fs0 x else return $ FL.Partial fs0
2695 case r of
2696 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2697 FL.Done b -> do
2698 let jump c = SplitOnSuffixSeqWordInit c s
2699 yieldProceed jump b
2700 Skip s -> skip (SplitOnSuffixSeqWordInit fs0 s)
2701 Stop -> return Stop
2703 where
2705 {-# INLINE go #-}
2706 go !_ !idx !wrd !st !fs = do
2707 res <- step (adaptState gst) st
2708 case res of
2709 Yield x s -> do
2710 let jump c = SplitOnSuffixSeqWordInit c s
2711 let wrd1 = addToWord wrd x
2712 r <- if withSep then fstep fs x else return $ FL.Partial fs
2713 case r of
2714 FL.Partial fs1 ->
2715 if idx /= maxIndex
2716 then go SPEC (idx + 1) wrd1 s fs1
2717 else if wrd1 .&. wordMask /= wordPat
2718 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2719 else do done fs >>= yieldProceed jump
2720 FL.Done b -> yieldProceed jump b
2721 Skip s -> go SPEC idx wrd s fs
2722 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2724 stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2725 go SPEC wrd0 st0 fs0
2727 where
2729 {-# INLINE go #-}
2730 go !_ !wrd !st !fs = do
2731 res <- step (adaptState gst) st
2732 case res of
2733 Yield x s -> do
2734 let jump c = SplitOnSuffixSeqWordInit c s
2735 wrd1 = addToWord wrd x
2736 old = (wordMask .&. wrd)
2737 `shiftR` (elemBits * (patLen - 1))
2738 r <-
2739 if withSep
2740 then fstep fs x
2741 else fstep fs (toEnum $ fromIntegral old)
2742 case r of
2743 FL.Partial fs1 ->
2744 if wrd1 .&. wordMask == wordPat
2745 then done fs1 >>= yieldProceed jump
2746 else go SPEC wrd1 s fs1
2747 FL.Done b -> yieldProceed jump b
2748 Skip s -> go SPEC wrd s fs
2749 Stop ->
2750 if wrd .&. wordMask == wordPat
2751 then return Stop
2752 else if withSep
2753 then do
2754 r <- done fs
2755 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2756 else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2758 -------------------------------
2759 -- General Pattern - Karp Rabin
2760 -------------------------------
2762 stepOuter gst (SplitOnSuffixSeqKRInit idx0 fs st0 rb rh0) = do
2763 res <- step (adaptState gst) st0
2764 case res of
2765 Yield x s -> do
2766 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2767 r <- if withSep then fstep fs x else return $ FL.Partial fs
2768 case r of
2769 FL.Partial fs1 ->
2770 skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2771 FL.Done b -> do
2772 let rst = RB.startOf rb
2773 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2774 yieldProceed jump b
2775 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 fs s rb rh0
2776 Stop -> return Stop
2778 stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2779 go SPEC 1 rh0 st0 fs0
2781 where
2783 go !_ !idx !rh st !fs = do
2784 res <- step (adaptState gst) st
2785 case res of
2786 Yield x s -> do
2787 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2788 r <- if withSep then fstep fs x else return $ FL.Partial fs
2789 case r of
2790 FL.Partial fs1 ->
2791 if idx /= maxIndex
2792 then go SPEC (idx + 1) rh1 s fs1
2793 else skip $
2794 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2795 !ringHash = fld addCksum 0 rb
2796 in if ringHash == patHash
2797 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2798 else SplitOnSuffixSeqKRLoop
2799 fs1 s rb rh1 ringHash
2800 FL.Done b -> do
2801 let rst = RB.startOf rb
2802 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2803 yieldProceed jump b
2804 Skip s -> go SPEC idx rh s fs
2805 Stop -> do
2806 -- do not issue a blank segment when we end at pattern
2807 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2808 then return Stop
2809 else if withSep
2810 then do
2811 r <- done fs
2812 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2813 else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2815 stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2816 go SPEC fs0 st0 rh0 cksum0
2818 where
2820 go !_ !fs !st !rh !cksum = do
2821 res <- step (adaptState gst) st
2822 case res of
2823 Yield x s -> do
2824 old <- liftIO $ peek rh
2825 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2826 let cksum1 = deltaCksum cksum old x
2827 r <- if withSep then fstep fs x else fstep fs old
2828 case r of
2829 FL.Partial fs1 ->
2830 if cksum1 /= patHash
2831 then go SPEC fs1 s rh1 cksum1
2832 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2833 FL.Done b -> do
2834 let rst = RB.startOf rb
2835 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2836 yieldProceed jump b
2837 Skip s -> go SPEC fs s rh cksum
2838 Stop ->
2839 if RB.unsafeEqArray rb rh patArr
2840 then return Stop
2841 else if withSep
2842 then do
2843 r <- done fs
2844 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2845 else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2847 stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2848 if RB.unsafeEqArray rb rh patArr
2849 then do
2850 r <- done fs
2851 let rst = RB.startOf rb
2852 jump c = SplitOnSuffixSeqKRInit 0 c st rb rst
2853 yieldProceed jump r
2854 else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2856 stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2857 r <- done fs
2858 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2859 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2860 old <- liftIO $ peek rh
2861 let rh1 = RB.advance rb rh
2862 r <- fstep fs old
2863 case r of
2864 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2865 FL.Done b -> do
2866 let jump c = SplitOnSuffixSeqKRDone (n - 1) c rb rh1
2867 yieldProceed jump b
2869-- Implement this as a fold or a parser instead.
2870-- This can be implemented easily using Rabin Karp
2871-- | Split post any one of the given patterns.
2873-- /Unimplemented/
2874{-# INLINE splitOnSuffixSeqAny #-}
2875splitOnSuffixSeqAny :: -- (Monad m, Unboxed a, Integral a) =>
2876 [Array a] -> Fold m a b -> Stream m a -> Stream m b
2877splitOnSuffixSeqAny _subseq _f _m = undefined
2878 -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
2880-- | Split on a prefixed separator element, dropping the separator. The
2881-- supplied 'Fold' is applied on the split segments.
2883-- @
2884-- > splitOnPrefix' p xs = Stream.toList $ Stream.splitOnPrefix p (Fold.toList) (Stream.fromList xs)
2885-- > splitOnPrefix' (== '.') ".a.b"
2886-- ["a","b"]
2887-- @
2889-- An empty stream results in an empty output stream:
2890-- @
2891-- > splitOnPrefix' (== '.') ""
2892-- []
2893-- @
2895-- An empty segment consisting of only a prefix is folded to the default output
2896-- of the fold:
2898-- @
2899-- > splitOnPrefix' (== '.') "."
2900-- [""]
2902-- > splitOnPrefix' (== '.') ".a.b."
2903-- ["a","b",""]
2905-- > splitOnPrefix' (== '.') ".a..b"
2906-- ["a","","b"]
2908-- @
2910-- A prefix is optional at the beginning of the stream:
2912-- @
2913-- > splitOnPrefix' (== '.') "a"
2914-- ["a"]
2916-- > splitOnPrefix' (== '.') "a.b"
2917-- ["a","b"]
2918-- @
2920-- 'splitOnPrefix' is an inverse of 'intercalatePrefix' with a single element:
2922-- > Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList . Stream.splitOnPrefix (== '.') Fold.toList === id
2924-- Assuming the input stream does not contain the separator:
2926-- > Stream.splitOnPrefix (== '.') Fold.toList . Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList === id
2928-- /Unimplemented/
2929{-# INLINE splitOnPrefix #-}
2930splitOnPrefix :: -- (IsStream t, MonadCatch m) =>
2931 (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
2932splitOnPrefix _predicate _f = undefined
2933 -- parseMany (Parser.sliceBeginBy predicate f)
2935-- Int list examples for splitOn:
2937-- >>> splitList [] [1,2,3,3,4]
2938-- > [[1],[2],[3],[3],[4]]
2940-- >>> splitList [5] [1,2,3,3,4]
2941-- > [[1,2,3,3,4]]
2943-- >>> splitList [1] [1,2,3,3,4]
2944-- > [[],[2,3,3,4]]
2946-- >>> splitList [4] [1,2,3,3,4]
2947-- > [[1,2,3,3],[]]
2949-- >>> splitList [2] [1,2,3,3,4]
2950-- > [[1],[3,3,4]]
2952-- >>> splitList [3] [1,2,3,3,4]
2953-- > [[1,2],[],[4]]
2955-- >>> splitList [3,3] [1,2,3,3,4]
2956-- > [[1,2],[4]]
2958-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
2959-- > [[],[]]
2961-- This can be implemented easily using Rabin Karp
2962-- | Split on any one of the given patterns.
2964-- /Unimplemented/
2966{-# INLINE splitOnAny #-}
2967splitOnAny :: -- (Monad m, Unboxed a, Integral a) =>
2968 [Array a] -> Fold m a b -> Stream m a -> Stream m b
2969splitOnAny _subseq _f _m =
2970 undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
2972------------------------------------------------------------------------------
2973-- Nested Container Transformation
2974------------------------------------------------------------------------------
2976{-# ANN type SplitState Fuse #-}
2977data SplitState s arr
2978 = SplitInitial s
2979 | SplitBuffering s arr
2980 | SplitSplitting s arr
2981 | SplitYielding arr (SplitState s arr)
2982 | SplitFinishing
2984-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2985-- split using a splitBy like combinator. The Fold would consume upto the
2986-- separator and return any leftover which can then be fed to the next fold.
2988-- We can revisit this once we have partial folds/parsers.
2990-- | Performs infix separator style splitting.
2991{-# INLINE_NORMAL splitInnerBy #-}
2992splitInnerBy
2993 :: Monad m
2994 => (f a -> m (f a, Maybe (f a))) -- splitter
2995 -> (f a -> f a -> m (f a)) -- joiner
2996 -> Stream m (f a)
2997 -> Stream m (f a)
2998splitInnerBy splitter joiner (Stream step1 state1) =
2999 Stream step (SplitInitial state1)
3001 where
3003 {-# INLINE_LATE step #-}
3004 step gst (SplitInitial st) = do
3005 r <- step1 gst st
3006 case r of
3007 Yield x s -> do
3008 (x1, mx2) <- splitter x
3009 return $ case mx2 of
3010 Nothing -> Skip (SplitBuffering s x1)
3011 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
3012 Skip s -> return $ Skip (SplitInitial s)
3013 Stop -> return Stop
3015 step gst (SplitBuffering st buf) = do
3016 r <- step1 gst st
3017 case r of
3018 Yield x s -> do
3019 (x1, mx2) <- splitter x
3020 buf' <- joiner buf x1
3021 return $ case mx2 of
3022 Nothing -> Skip (SplitBuffering s buf')
3023 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
3024 Skip s -> return $ Skip (SplitBuffering s buf)
3025 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
3027 step _ (SplitSplitting st buf) = do
3028 (x1, mx2) <- splitter buf
3029 return $ case mx2 of
3030 Nothing -> Skip $ SplitBuffering st x1
3031 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
3033 step _ (SplitYielding x next) = return $ Yield x next
3034 step _ SplitFinishing = return Stop
3036-- | Performs infix separator style splitting.
3037{-# INLINE_NORMAL splitInnerBySuffix #-}
3038splitInnerBySuffix
3039 :: (Monad m, Eq (f a), Monoid (f a))
3040 => (f a -> m (f a, Maybe (f a))) -- splitter
3041 -> (f a -> f a -> m (f a)) -- joiner
3042 -> Stream m (f a)
3043 -> Stream m (f a)
3044splitInnerBySuffix splitter joiner (Stream step1 state1) =
3045 Stream step (SplitInitial state1)
3047 where
3049 {-# INLINE_LATE step #-}
3050 step gst (SplitInitial st) = do
3051 r <- step1 gst st
3052 case r of
3053 Yield x s -> do
3054 (x1, mx2) <- splitter x
3055 return $ case mx2 of
3056 Nothing -> Skip (SplitBuffering s x1)
3057 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
3058 Skip s -> return $ Skip (SplitInitial s)
3059 Stop -> return Stop
3061 step gst (SplitBuffering st buf) = do
3062 r <- step1 gst st
3063 case r of
3064 Yield x s -> do
3065 (x1, mx2) <- splitter x
3066 buf' <- joiner buf x1
3067 return $ case mx2 of
3068 Nothing -> Skip (SplitBuffering s buf')
3069 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
3070 Skip s -> return $ Skip (SplitBuffering s buf)
3071 Stop -> return $
3072 if buf == mempty
3073 then Stop
3074 else Skip (SplitYielding buf SplitFinishing)
3076 step _ (SplitSplitting st buf) = do
3077 (x1, mx2) <- splitter buf
3078 return $ case mx2 of
3079 Nothing -> Skip $ SplitBuffering st x1
3080 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
3082 step _ (SplitYielding x next) = return $ Yield x next
3083 step _ SplitFinishing = return Stop
3085------------------------------------------------------------------------------
3086-- Trimming
3087------------------------------------------------------------------------------
3089-- | Drop prefix from the input stream if present.
3091-- Space: @O(1)@
3093-- /Unimplemented/
3094{-# INLINE dropPrefix #-}
3095dropPrefix ::
3096 -- (Monad m, Eq a) =>
3097 Stream m a -> Stream m a -> Stream m a
3098dropPrefix = error "Not implemented yet!"
3100-- | Drop all matching infix from the input stream if present. Infix stream
3101-- may be consumed multiple times.
3103-- Space: @O(n)@ where n is the length of the infix.
3105-- /Unimplemented/
3106{-# INLINE dropInfix #-}
3107dropInfix ::
3108 -- (Monad m, Eq a) =>
3109 Stream m a -> Stream m a -> Stream m a
3110dropInfix = error "Not implemented yet!"
3112-- | Drop suffix from the input stream if present. Suffix stream may be
3113-- consumed multiple times.
3115-- Space: @O(n)@ where n is the length of the suffix.
3117-- /Unimplemented/
3118{-# INLINE dropSuffix #-}
3119dropSuffix ::
3120 -- (Monad m, Eq a) =>
3121 Stream m a -> Stream m a -> Stream m a
3122dropSuffix = error "Not implemented yet!"