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
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.
17-- These combinators involve transformation, generation, elimination so can be
18-- classified under any of those.
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.
26module Streamly.Internal.Data.Stream.StreamD.Nesting
29 -- | Combining streams to generate streams.
31 -- ** Combine Two Streams
32 -- | Functions ending in the shape:
34 -- @t m a -> t m a -> t m a@.
37 -- | Append a stream after another. A special case of concatMap or
43 -- | Interleave elements from two streams alternately. A special case of
44 -- concatUnfoldInterleave.
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 concatUnfoldRoundrobin.
55 , roundRobin -- interleaveFair?/ParallelFair
58 -- | Zip corresponding elements of two streams.
63 -- | Interleave elements from two streams based on a condition.
67 -- ** Combine N Streams
68 -- | Functions generally ending in these shapes:
71 -- concat: f (t m a) -> t m a
72 -- concatMap: (a -> t m b) -> t m a -> t m b
73 -- concatUnfold: Unfold m a b -> t m a -> t m b
77 -- | Generate streams by mapping a stream generator on each element of an
78 -- input stream, append the resulting streams and flatten.
83 -- | Generate streams by using an unfold on each element of an input
84 -- stream, append the resulting streams and flatten. A special case of
87 , ConcatUnfoldInterleaveState (..)
88 , concatUnfoldInterleave
89 , concatUnfoldRoundrobin
92 -- | Like concatUnfold but intersperses an effect between the streams. A
93 -- special case of gintercalate.
98 -- | Like concatUnfold but intersperses streams from another source between
99 -- the streams from the first source.
104 -- | Folding and Parsing chunks of streams to eliminate nested streams.
105 -- Functions generally ending in these shapes:
108 -- f (Fold m a b) -> t m a -> t m b
109 -- f (Parser m a b) -> t m a -> t m b
113 -- | Apply folds on a stream.
117 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
118 -- concatUnfold. concatMap generates a stream from single values in a
119 -- stream and flattens, parseMany does the opposite of flattening by
120 -- splitting the stream and then folds each such split to single value in
121 -- the output stream.
126 -- | Group segments of a stream and fold. Special case of parsing.
133 -- | A special case of parsing.
138 -- * Transform (Nested Containers)
139 -- | Opposite to compact in ArrayStream
147import Control.Exception (assert)
148import Control.Monad.Catch (MonadThrow, throwM)
149import Control.Monad.IO.Class (MonadIO(..))
150import Data.Bits (shiftR, shiftL, (.|.), (.&.))
151#if __GLASGOW_HASKELL__ >= 801
152import Data.Functor.Identity ( Identity )
154import Data.Word (Word32)
155import Foreign.Storable (Storable(..))
156import Fusion.Plugin.Types (Fuse(..))
157import GHC.Types (SPEC(..))
159import Streamly.Internal.Data.Array.Foreign.Types (Array(..))
160import Streamly.Internal.Data.Fold.Types (Fold(..))
161import Streamly.Internal.Data.Parser (ParseError(..))
162import Streamly.Internal.Data.Unfold.Types (Unfold(..))
164import qualified Streamly.Internal.Data.Array.Foreign.Types as A
165import qualified Streamly.Internal.Data.Fold as FL
166import qualified Streamly.Internal.Data.Parser as PR
167import qualified Streamly.Internal.Data.Parser.ParserD as PRD
168import qualified Streamly.Internal.Ring.Foreign as RB
170import Streamly.Internal.Data.Stream.StreamD.Type
171import Streamly.Internal.Data.SVar
173import Prelude hiding (concatMap, mapM, zipWith)
175------------------------------------------------------------------------------
177------------------------------------------------------------------------------
179data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
181-- Note that this could be much faster compared to the CPS stream. However, as
182-- the number of streams being composed increases this may become expensive.
183-- Need to see where the breaking point is between the two.
185{-# INLINE_NORMAL append #-}
186append :: Monad m => Stream m a -> Stream m a -> Stream m a
187append (Stream step1 state1) (Stream step2 state2) =
188 Stream step (AppendFirst state1)
192 {-# INLINE_LATE step #-}
193 step gst (AppendFirst st) = do
196 Yield a s -> Yield a (AppendFirst s)
197 Skip s -> Skip (AppendFirst s)
198 Stop -> Skip (AppendSecond state2)
200 step gst (AppendSecond st) = do
203 Yield a s -> Yield a (AppendSecond s)
204 Skip s -> Skip (AppendSecond s)
207------------------------------------------------------------------------------
209------------------------------------------------------------------------------
211data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
212 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
214{-# INLINE_NORMAL interleave #-}
215interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
216interleave (Stream step1 state1) (Stream step2 state2) =
217 Stream step (InterleaveFirst state1 state2)
221 {-# INLINE_LATE step #-}
222 step gst (InterleaveFirst st1 st2) = do
225 Yield a s -> Yield a (InterleaveSecond s st2)
226 Skip s -> Skip (InterleaveFirst s st2)
227 Stop -> Skip (InterleaveSecondOnly st2)
229 step gst (InterleaveSecond st1 st2) = do
232 Yield a s -> Yield a (InterleaveFirst st1 s)
233 Skip s -> Skip (InterleaveSecond st1 s)
234 Stop -> Skip (InterleaveFirstOnly st1)
236 step gst (InterleaveFirstOnly st1) = do
239 Yield a s -> Yield a (InterleaveFirstOnly s)
240 Skip s -> Skip (InterleaveFirstOnly s)
243 step gst (InterleaveSecondOnly st2) = do
246 Yield a s -> Yield a (InterleaveSecondOnly s)
247 Skip s -> Skip (InterleaveSecondOnly s)
250{-# INLINE_NORMAL interleaveMin #-}
251interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
252interleaveMin (Stream step1 state1) (Stream step2 state2) =
253 Stream step (InterleaveFirst state1 state2)
257 {-# INLINE_LATE step #-}
258 step gst (InterleaveFirst st1 st2) = do
261 Yield a s -> Yield a (InterleaveSecond s st2)
262 Skip s -> Skip (InterleaveFirst s st2)
265 step gst (InterleaveSecond st1 st2) = do
268 Yield a s -> Yield a (InterleaveFirst st1 s)
269 Skip s -> Skip (InterleaveSecond st1 s)
272 step _ (InterleaveFirstOnly _) = undefined
273 step _ (InterleaveSecondOnly _) = undefined
275{-# INLINE_NORMAL interleaveSuffix #-}
276interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
277interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
278 Stream step (InterleaveFirst state1 state2)
282 {-# INLINE_LATE step #-}
283 step gst (InterleaveFirst st1 st2) = do
286 Yield a s -> Yield a (InterleaveSecond s st2)
287 Skip s -> Skip (InterleaveFirst s st2)
290 step gst (InterleaveSecond st1 st2) = do
293 Yield a s -> Yield a (InterleaveFirst st1 s)
294 Skip s -> Skip (InterleaveSecond st1 s)
295 Stop -> Skip (InterleaveFirstOnly st1)
297 step gst (InterleaveFirstOnly st1) = do
300 Yield a s -> Yield a (InterleaveFirstOnly s)
301 Skip s -> Skip (InterleaveFirstOnly s)
304 step _ (InterleaveSecondOnly _) = undefined
306data InterleaveInfixState s1 s2 a
307 = InterleaveInfixFirst s1 s2
308 | InterleaveInfixSecondBuf s1 s2
309 | InterleaveInfixSecondYield s1 s2 a
310 | InterleaveInfixFirstYield s1 s2 a
311 | InterleaveInfixFirstOnly s1
313{-# INLINE_NORMAL interleaveInfix #-}
314interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
315interleaveInfix (Stream step1 state1) (Stream step2 state2) =
316 Stream step (InterleaveInfixFirst state1 state2)
320 {-# INLINE_LATE step #-}
321 step gst (InterleaveInfixFirst st1 st2) = do
324 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
325 Skip s -> Skip (InterleaveInfixFirst s st2)
328 step gst (InterleaveInfixSecondBuf st1 st2) = do
331 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
332 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
333 Stop -> Skip (InterleaveInfixFirstOnly st1)
335 step gst (InterleaveInfixSecondYield st1 st2 x) = do
338 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
339 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
342 step _ (InterleaveInfixFirstYield st1 st2 x) = do
343 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
345 step gst (InterleaveInfixFirstOnly st1) = do
348 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
349 Skip s -> Skip (InterleaveInfixFirstOnly s)
352------------------------------------------------------------------------------
354------------------------------------------------------------------------------
356{-# INLINE_NORMAL roundRobin #-}
357roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
358roundRobin (Stream step1 state1) (Stream step2 state2) =
359 Stream step (InterleaveFirst state1 state2)
363 {-# INLINE_LATE step #-}
364 step gst (InterleaveFirst st1 st2) = do
367 Yield a s -> Yield a (InterleaveSecond s st2)
368 Skip s -> Skip (InterleaveSecond s st2)
369 Stop -> Skip (InterleaveSecondOnly st2)
371 step gst (InterleaveSecond st1 st2) = do
374 Yield a s -> Yield a (InterleaveFirst st1 s)
375 Skip s -> Skip (InterleaveFirst st1 s)
376 Stop -> Skip (InterleaveFirstOnly st1)
378 step gst (InterleaveSecondOnly st2) = do
381 Yield a s -> Yield a (InterleaveSecondOnly s)
382 Skip s -> Skip (InterleaveSecondOnly s)
385 step gst (InterleaveFirstOnly st1) = do
388 Yield a s -> Yield a (InterleaveFirstOnly s)
389 Skip s -> Skip (InterleaveFirstOnly s)
392------------------------------------------------------------------------------
394------------------------------------------------------------------------------
396{-# INLINE_NORMAL zipWithM #-}
398 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
399zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
401 {-# INLINE_LATE step #-}
402 step gst (sa, sb, Nothing) = do
403 r <- stepa (adaptState gst) sa
406 Yield x sa' -> Skip (sa', sb, Just x)
407 Skip sa' -> Skip (sa', sb, Nothing)
410 step gst (sa, sb, Just x) = do
411 r <- stepb (adaptState gst) sb
415 return $ Yield z (sa, sb', Nothing)
416 Skip sb' -> return $ Skip (sa, sb', Just x)
419#if __GLASGOW_HASKELL__ >= 801
420{-# RULES "zipWithM xs xs"
421 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
424{-# INLINE zipWith #-}
425zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
426zipWith f = zipWithM (\a b -> return (f a b))
428------------------------------------------------------------------------------
430------------------------------------------------------------------------------
432{-# INLINE_NORMAL mergeByM #-}
435 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
436mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
437 Stream step (Just ta, Just tb, Nothing, Nothing)
439 {-# INLINE_LATE step #-}
441 -- one of the values is missing, and the corresponding stream is running
442 step gst (Just sa, sb, Nothing, b) = do
445 Yield a sa' -> Skip (Just sa', sb, Just a, b)
446 Skip sa' -> Skip (Just sa', sb, Nothing, b)
447 Stop -> Skip (Nothing, sb, Nothing, b)
449 step gst (sa, Just sb, a, Nothing) = do
452 Yield b sb' -> Skip (sa, Just sb', a, Just b)
453 Skip sb' -> Skip (sa, Just sb', a, Nothing)
454 Stop -> Skip (sa, Nothing, a, Nothing)
456 -- both the values are available
457 step _ (sa, sb, Just a, Just b) = do
460 GT -> Yield b (sa, sb, Just a, Nothing)
461 _ -> Yield a (sa, sb, Nothing, Just b)
463 -- one of the values is missing, corresponding stream is done
464 step _ (Nothing, sb, Nothing, Just b) =
465 return $ Yield b (Nothing, sb, Nothing, Nothing)
467 step _ (sa, Nothing, Just a, Nothing) =
468 return $ Yield a (sa, Nothing, Nothing, Nothing)
470 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
472{-# INLINE mergeBy #-}
475 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
476mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
478------------------------------------------------------------------------------
479-- Combine N Streams - concatUnfold
480------------------------------------------------------------------------------
482data ConcatUnfoldInterleaveState o i =
483 ConcatUnfoldInterleaveOuter o [i]
484 | ConcatUnfoldInterleaveInner o [i]
485 | ConcatUnfoldInterleaveInnerL [i] [i]
486 | ConcatUnfoldInterleaveInnerR [i] [i]
488-- XXX use arrays to store state instead of lists.
489-- XXX In general we can use different scheduling strategies e.g. how to
490-- schedule the outer vs inner loop or assigning weights to different streams
491-- or outer and inner loops.
493-- After a yield, switch to the next stream. Do not switch streams on Skip.
494-- Yield from outer stream switches to the inner stream.
496-- There are two choices here, (1) exhaust the outer stream first and then
497-- start yielding from the inner streams, this is much simpler to implement,
498-- (2) yield at least one element from an inner stream before going back to
499-- outer stream and opening the next stream from it.
501-- Ideally, we need some scheduling bias to inner streams vs outer stream.
502-- Maybe we can configure the behavior.
504{-# INLINE_NORMAL concatUnfoldInterleave #-}
505concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
506concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
507 Stream step (ConcatUnfoldInterleaveOuter ost [])
509 {-# INLINE_LATE step #-}
510 step gst (ConcatUnfoldInterleaveOuter o ls) = do
511 r <- ostep (adaptState gst) o
515 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
516 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
517 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
519 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
520 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
523 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
524 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
525 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
527 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
528 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
529 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
531 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
534 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
535 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
536 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
538 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
539 step _ (ConcatUnfoldInterleaveInnerR ls []) =
540 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
542 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
545 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
546 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
547 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
549-- XXX In general we can use different scheduling strategies e.g. how to
550-- schedule the outer vs inner loop or assigning weights to different streams
551-- or outer and inner loops.
553-- This could be inefficient if the tasks are too small.
555-- Compared to concatUnfoldInterleave this one switches streams on Skips.
557{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
558concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
559concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
560 Stream step (ConcatUnfoldInterleaveOuter ost [])
562 {-# INLINE_LATE step #-}
563 step gst (ConcatUnfoldInterleaveOuter o ls) = do
564 r <- ostep (adaptState gst) o
568 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
569 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
570 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
572 step _ (ConcatUnfoldInterleaveInner o []) =
573 return $ Skip (ConcatUnfoldInterleaveOuter o [])
575 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
578 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
579 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
580 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
582 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
583 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
584 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
586 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
589 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
590 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
591 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
593 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
594 step _ (ConcatUnfoldInterleaveInnerR ls []) =
595 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
597 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
600 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
601 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
602 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
604------------------------------------------------------------------------------
605-- Combine N Streams - interpose
606------------------------------------------------------------------------------
608{-# ANN type InterposeSuffixState Fuse #-}
609data InterposeSuffixState s1 i1 =
610 InterposeSuffixFirst s1
611 -- | InterposeSuffixFirstYield s1 i1
612 | InterposeSuffixFirstInner s1 i1
613 | InterposeSuffixSecond s1
615-- Note that if an unfolded layer turns out to be nil we still emit the
616-- separator effect. An alternate behavior could be to emit the separator
617-- effect only if at least one element has been yielded by the unfolding.
618-- However, that becomes a bit complicated, so we have chosen the former
620{-# INLINE_NORMAL interposeSuffix #-}
623 => m c -> Unfold m b c -> Stream m b -> Stream m c
626 (Unfold istep1 inject1) (Stream step1 state1) =
627 Stream step (InterposeSuffixFirst state1)
631 {-# INLINE_LATE step #-}
632 step gst (InterposeSuffixFirst s1) = do
633 r <- step1 (adaptState gst) s1
637 i `seq` return (Skip (InterposeSuffixFirstInner s i))
638 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
639 Skip s -> return $ Skip (InterposeSuffixFirst s)
643 step _ (InterposeSuffixFirstYield s1 i1) = do
646 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
647 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
648 Stop -> Skip (InterposeSuffixFirst s1)
651 step _ (InterposeSuffixFirstInner s1 i1) = do
654 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
655 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
656 Stop -> Skip (InterposeSuffixSecond s1)
658 step _ (InterposeSuffixSecond s1) = do
660 return $ Yield r (InterposeSuffixFirst s1)
662{-# ANN type InterposeState Fuse #-}
663data InterposeState s1 i1 a =
665 -- | InterposeFirstYield s1 i1
666 | InterposeFirstInner s1 i1
667 | InterposeFirstInject s1
668 -- | InterposeFirstBuf s1 i1
669 | InterposeSecondYield s1 i1
670 -- -- | InterposeSecondYield s1 i1 a
671 -- -- | InterposeFirstResume s1 i1 a
673-- Note that this only interposes the pure values, we may run many effects to
674-- generate those values as some effects may not generate anything (Skip).
675{-# INLINE_NORMAL interpose #-}
676interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
679 (Unfold istep1 inject1) (Stream step1 state1) =
680 Stream step (InterposeFirst state1)
684 {-# INLINE_LATE step #-}
685 step gst (InterposeFirst s1) = do
686 r <- step1 (adaptState gst) s1
690 i `seq` return (Skip (InterposeFirstInner s i))
691 -- i `seq` return (Skip (InterposeFirstYield s i))
692 Skip s -> return $ Skip (InterposeFirst s)
696 step _ (InterposeFirstYield s1 i1) = do
699 Yield x i' -> Yield x (InterposeFirstInner s1 i')
700 Skip i' -> Skip (InterposeFirstYield s1 i')
701 Stop -> Skip (InterposeFirst s1)
704 step _ (InterposeFirstInner s1 i1) = do
707 Yield x i' -> Yield x (InterposeFirstInner s1 i')
708 Skip i' -> Skip (InterposeFirstInner s1 i')
709 Stop -> Skip (InterposeFirstInject s1)
711 step gst (InterposeFirstInject s1) = do
712 r <- step1 (adaptState gst) s1
716 -- i `seq` return (Skip (InterposeFirstBuf s i))
717 i `seq` return (Skip (InterposeSecondYield s i))
718 Skip s -> return $ Skip (InterposeFirstInject s)
722 step _ (InterposeFirstBuf s1 i1) = do
725 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
726 Skip i' -> Skip (InterposeFirstBuf s1 i')
731 step _ (InterposeSecondYield s1 i1 v) = do
733 return $ Yield r (InterposeFirstResume s1 i1 v)
735 step _ (InterposeSecondYield s1 i1) = do
737 return $ Yield r (InterposeFirstInner s1 i1)
740 step _ (InterposeFirstResume s1 i1 v) = do
741 return $ Yield v (InterposeFirstInner s1 i1)
744------------------------------------------------------------------------------
745-- Combine N Streams - intercalate
746------------------------------------------------------------------------------
748data ICUState s1 s2 i1 i2 =
753 | ICUFirstInner s1 s2 i1
754 | ICUSecondInner s1 s2 i2
755 | ICUFirstOnlyInner s1 i1
756 | ICUSecondOnlyInner s2 i2
758-- | Interleave streams (full streams, not the elements) unfolded from two
759-- input streams and concat. Stop when the first stream stops. If the second
760-- stream ends before the first one then first stream still keeps running alone
761-- without any interleaving with the second stream.
763-- [a1, a2, ... an] [b1, b2 ...]
764-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
765-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
766-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
768{-# INLINE_NORMAL gintercalateSuffix #-}
771 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
773 (Unfold istep1 inject1) (Stream step1 state1)
774 (Unfold istep2 inject2) (Stream step2 state2) =
775 Stream step (ICUFirst state1 state2)
779 {-# INLINE_LATE step #-}
780 step gst (ICUFirst s1 s2) = do
781 r <- step1 (adaptState gst) s1
785 i `seq` return (Skip (ICUFirstInner s s2 i))
786 Skip s -> return $ Skip (ICUFirst s s2)
789 step gst (ICUFirstOnly s1) = do
790 r <- step1 (adaptState gst) s1
794 i `seq` return (Skip (ICUFirstOnlyInner s i))
795 Skip s -> return $ Skip (ICUFirstOnly s)
798 step _ (ICUFirstInner s1 s2 i1) = do
801 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
802 Skip i' -> Skip (ICUFirstInner s1 s2 i')
803 Stop -> Skip (ICUSecond s1 s2)
805 step _ (ICUFirstOnlyInner s1 i1) = do
808 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
809 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
810 Stop -> Skip (ICUFirstOnly s1)
812 step gst (ICUSecond s1 s2) = do
813 r <- step2 (adaptState gst) s2
817 i `seq` return (Skip (ICUSecondInner s1 s i))
818 Skip s -> return $ Skip (ICUSecond s1 s)
819 Stop -> return $ Skip (ICUFirstOnly s1)
821 step _ (ICUSecondInner s1 s2 i2) = do
824 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
825 Skip i' -> Skip (ICUSecondInner s1 s2 i')
826 Stop -> Skip (ICUFirst s1 s2)
828 step _ (ICUSecondOnly _s2) = undefined
829 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
831data ICALState s1 s2 i1 i2 a =
833 -- | ICALFirstYield s1 s2 i1
834 | ICALFirstInner s1 s2 i1
836 | ICALFirstOnlyInner s1 i1
837 | ICALSecondInject s1 s2
838 | ICALFirstInject s1 s2 i2
839 -- | ICALFirstBuf s1 s2 i1 i2
840 | ICALSecondInner s1 s2 i1 i2
841 -- -- | ICALSecondInner s1 s2 i1 i2 a
842 -- -- | ICALFirstResume s1 s2 i1 i2 a
844-- | Interleave streams (full streams, not the elements) unfolded from two
845-- input streams and concat. Stop when the first stream stops. If the second
846-- stream ends before the first one then first stream still keeps running alone
847-- without any interleaving with the second stream.
849-- [a1, a2, ... an] [b1, b2 ...]
850-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
851-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
852-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
854{-# INLINE_NORMAL gintercalate #-}
857 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
859 (Unfold istep1 inject1) (Stream step1 state1)
860 (Unfold istep2 inject2) (Stream step2 state2) =
861 Stream step (ICALFirst state1 state2)
865 {-# INLINE_LATE step #-}
866 step gst (ICALFirst s1 s2) = do
867 r <- step1 (adaptState gst) s1
871 i `seq` return (Skip (ICALFirstInner s s2 i))
872 -- i `seq` return (Skip (ICALFirstYield s s2 i))
873 Skip s -> return $ Skip (ICALFirst s s2)
877 step _ (ICALFirstYield s1 s2 i1) = do
880 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
881 Skip i' -> Skip (ICALFirstYield s1 s2 i')
882 Stop -> Skip (ICALFirst s1 s2)
885 step _ (ICALFirstInner s1 s2 i1) = do
888 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
889 Skip i' -> Skip (ICALFirstInner s1 s2 i')
890 Stop -> Skip (ICALSecondInject s1 s2)
892 step gst (ICALFirstOnly s1) = do
893 r <- step1 (adaptState gst) s1
897 i `seq` return (Skip (ICALFirstOnlyInner s i))
898 Skip s -> return $ Skip (ICALFirstOnly s)
901 step _ (ICALFirstOnlyInner s1 i1) = do
904 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
905 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
906 Stop -> Skip (ICALFirstOnly s1)
908 -- We inject the second stream even before checking if the first stream
909 -- would yield any more elements. There is no clear choice whether we
910 -- should do this before or after that. Doing it after may make the state
911 -- machine a bit simpler though.
912 step gst (ICALSecondInject s1 s2) = do
913 r <- step2 (adaptState gst) s2
917 i `seq` return (Skip (ICALFirstInject s1 s i))
918 Skip s -> return $ Skip (ICALSecondInject s1 s)
919 Stop -> return $ Skip (ICALFirstOnly s1)
921 step gst (ICALFirstInject s1 s2 i2) = do
922 r <- step1 (adaptState gst) s1
926 i `seq` return (Skip (ICALSecondInner s s2 i i2))
927 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
928 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
932 step _ (ICALFirstBuf s1 s2 i1 i2) = do
935 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
936 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
939 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
942 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
943 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
944 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
947 step _ (ICALSecondInner s1 s2 i1 i2) = do
950 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
951 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
952 Stop -> Skip (ICALFirstInner s1 s2 i1)
953 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
956 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
957 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
960------------------------------------------------------------------------------
962------------------------------------------------------------------------------
964{-# ANN type ParseChunksState Fuse #-}
965data ParseChunksState x inpBuf st pst =
966 ParseChunksInit inpBuf st
967 | ParseChunksInitLeftOver inpBuf
968 | ParseChunksStream st inpBuf !pst
969 | ParseChunksBuf inpBuf st inpBuf !pst
970 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
972{-# INLINE_NORMAL parseMany #-}
978parseMany (PRD.Parser pstep initial extract) (Stream step state) =
979 Stream stepOuter (ParseChunksInit [] state)
983 {-# INLINE_LATE stepOuter #-}
984 -- Buffer is empty, get the first element from the stream, initialize the
985 -- fold and then go to stream processing loop.
986 stepOuter gst (ParseChunksInit [] st) = do
987 r <- step (adaptState gst) st
989 Yield x s -> initial >>= return . Skip . ParseChunksBuf [x] s []
990 Skip s -> return $ Skip $ ParseChunksInit [] s
993 -- Buffer is not empty, go to buffered processing loop
994 stepOuter _ (ParseChunksInit src st) = do
995 initial >>= return . Skip . ParseChunksBuf src st []
997 -- XXX we just discard any leftover input at the end
998 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1000 -- Buffer is empty, process elements from the stream
1001 stepOuter gst (ParseChunksStream st buf pst) = do
1002 r <- step (adaptState gst) st
1007 PR.Partial 0 pst1 ->
1008 return $ Skip $ ParseChunksStream s [] pst1
1009 PR.Partial n pst1 -> do
1010 assert (n <= length (x:buf)) (return ())
1011 let src0 = Prelude.take n (x:buf)
1012 src = Prelude.reverse src0
1013 return $ Skip $ ParseChunksBuf src s [] pst1
1014 PR.Continue 0 pst1 ->
1015 return $ Skip $ ParseChunksStream s (x:buf) pst1
1016 PR.Continue n pst1 -> do
1017 assert (n <= length (x:buf)) (return ())
1018 let (src0, buf1) = splitAt n (x:buf)
1019 src = Prelude.reverse src0
1020 return $ Skip $ ParseChunksBuf src s buf1 pst1
1023 ParseChunksYield b (ParseChunksInit [] s)
1025 assert (n <= length (x:buf)) (return ())
1026 let src = Prelude.reverse (Prelude.take n (x:buf))
1028 ParseChunksYield b (ParseChunksInit src s)
1029 PR.Error err -> throwM $ ParseError err
1030 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1033 let src = Prelude.reverse buf
1035 ParseChunksYield b (ParseChunksInitLeftOver src)
1037 -- go back to stream processing mode
1038 stepOuter _ (ParseChunksBuf [] s buf pst) =
1039 return $ Skip $ ParseChunksStream s buf pst
1041 -- buffered processing loop
1042 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1045 PR.Partial 0 pst1 ->
1046 return $ Skip $ ParseChunksBuf xs s [] pst1
1047 PR.Partial n pst1 -> do
1048 assert (n <= length (x:buf)) (return ())
1049 let src0 = Prelude.take n (x:buf)
1050 src = Prelude.reverse src0 ++ xs
1051 return $ Skip $ ParseChunksBuf src s [] pst1
1052 PR.Continue 0 pst1 ->
1053 return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1054 PR.Continue n pst1 -> do
1055 assert (n <= length (x:buf)) (return ())
1056 let (src0, buf1) = splitAt n (x:buf)
1057 src = Prelude.reverse src0 ++ xs
1058 return $ Skip $ ParseChunksBuf src s buf1 pst1
1060 return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1062 assert (n <= length (x:buf)) (return ())
1063 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1064 return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1065 PR.Error err -> throwM $ ParseError err
1067 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1069{-# ANN type ConcatParseState Fuse #-}
1070data ConcatParseState x inpBuf st p =
1071 ConcatParseInit inpBuf st p
1072 | ConcatParseInitLeftOver inpBuf
1073 | ConcatParseStream st inpBuf p
1074 | ConcatParseBuf inpBuf st inpBuf p
1075 | ConcatParseYield x (ConcatParseState x inpBuf st p)
1077{-# INLINE_NORMAL parseIterate #-}
1080 => (b -> PRD.Parser m a b)
1084parseIterate func seed (Stream step state) =
1085 Stream stepOuter (ConcatParseInit [] state (func seed))
1089 {-# INLINE_LATE stepOuter #-}
1090 -- Buffer is empty, go to stream processing loop
1091 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1092 initial >>= \r -> return $ Skip $ ConcatParseStream st []
1093 (PRD.Parser pstep (return r) extract)
1095 -- Buffer is not empty, go to buffered processing loop
1096 stepOuter _ (ConcatParseInit src st
1097 (PRD.Parser pstep initial extract)) = do
1098 initial >>= \r -> return $ Skip $ ConcatParseBuf src st []
1099 (PRD.Parser pstep (return r) extract)
1101 -- XXX we just discard any leftover input at the end
1102 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1104 -- Buffer is empty process elements from the stream
1105 stepOuter gst (ConcatParseStream st buf
1106 p@(PRD.Parser pstep initial extract)) = do
1107 r <- step (adaptState gst) st
1113 PR.Partial 0 pst1 ->
1114 return $ Skip $ ConcatParseStream s []
1115 (PRD.Parser pstep (return pst1) extract)
1116 PR.Partial n pst1 -> do
1117 assert (n <= length (x:buf)) (return ())
1118 let src0 = Prelude.take n (x:buf)
1119 src = Prelude.reverse src0
1120 return $ Skip $ ConcatParseBuf src s []
1121 (PRD.Parser pstep (return pst1) extract)
1122 -- PR.Continue 0 pst1 ->
1123 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1124 PR.Continue n pst1 -> do
1125 assert (n <= length (x:buf)) (return ())
1126 let (src0, buf1) = splitAt n (x:buf)
1127 src = Prelude.reverse src0
1128 return $ Skip $ ConcatParseBuf src s buf1
1129 (PRD.Parser pstep (return pst1) extract)
1130 -- XXX Specialize for Stop 0 common case?
1132 assert (n <= length (x:buf)) (return ())
1133 let src = Prelude.reverse (Prelude.take n (x:buf))
1135 ConcatParseYield b (ConcatParseInit src s (func b))
1136 PR.Error err -> throwM $ ParseError err
1137 Skip s -> return $ Skip $ ConcatParseStream s buf p
1141 let src = Prelude.reverse buf
1143 ConcatParseYield b (ConcatParseInitLeftOver src)
1145 -- go back to stream processing mode
1146 stepOuter _ (ConcatParseBuf [] s buf p) =
1147 return $ Skip $ ConcatParseStream s buf p
1149 -- buffered processing loop
1150 stepOuter _ (ConcatParseBuf (x:xs) s buf
1151 (PRD.Parser pstep initial extract)) = do
1155 PR.Partial 0 pst1 ->
1156 return $ Skip $ ConcatParseBuf xs s []
1157 (PRD.Parser pstep (return pst1) extract)
1158 PR.Partial n pst1 -> do
1159 assert (n <= length (x:buf)) (return ())
1160 let src0 = Prelude.take n (x:buf)
1161 src = Prelude.reverse src0 ++ xs
1162 return $ Skip $ ConcatParseBuf src s []
1163 (PRD.Parser pstep (return pst1) extract)
1164 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1165 PR.Continue n pst1 -> do
1166 assert (n <= length (x:buf)) (return ())
1167 let (src0, buf1) = splitAt n (x:buf)
1168 src = Prelude.reverse src0 ++ xs
1169 return $ Skip $ ConcatParseBuf src s buf1
1170 (PRD.Parser pstep (return pst1) extract)
1171 -- XXX Specialize for Stop 0 common case?
1173 assert (n <= length (x:buf)) (return ())
1174 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1175 return $ Skip $ ConcatParseYield b
1176 (ConcatParseInit src s (func b))
1177 PR.Error err -> throwM $ ParseError err
1179 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1181------------------------------------------------------------------------------
1183------------------------------------------------------------------------------
1185data GroupByState st fs a b
1188 | GroupingInitWith st !a
1189 | GroupingDoWith st !fs !a
1190 | GroupingYield !b (GroupByState st fs a b)
1193{-# INLINE_NORMAL groupsBy #-}
1199groupsBy cmp (Fold fstep initial done) (Stream step state) =
1200 Stream stepOuter (GroupingInit state)
1204 {-# INLINE_LATE stepOuter #-}
1205 stepOuter _ (GroupingInit st) = do
1206 -- XXX Note that if the stream stops without yielding a single element
1207 -- in the group we discard the "initial" effect.
1211 FL.Partial s -> Skip $ GroupingDo st s
1212 FL.Done b -> Yield b $ GroupingInit st
1213 stepOuter gst (GroupingDo st fs) = do
1214 res <- step (adaptState gst) st
1219 FL.Partial fs1 -> go SPEC x s fs1
1220 FL.Done b -> return $ Yield b (GroupingInit s)
1221 Skip s -> return $ Skip $ GroupingDo s fs
1226 go !_ prev stt !acc = do
1227 res <- step (adaptState gst) stt
1234 FL.Partial fs1 -> go SPEC prev s fs1
1235 FL.Done b -> return $ Yield b (GroupingInit s)
1238 return $ Yield r (GroupingInitWith s x)
1239 Skip s -> go SPEC prev s acc
1240 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1241 stepOuter _ (GroupingInitWith st x) = do
1245 FL.Partial s -> Skip $ GroupingDoWith st s x
1246 FL.Done b -> Yield b $ GroupingInitWith st x
1247 stepOuter gst (GroupingDoWith st fs prev) = do
1248 res <- fstep fs prev
1250 FL.Partial fs1 -> go SPEC st fs1
1251 FL.Done b -> return $ Yield b (GroupingInit st)
1255 -- XXX code duplicated from the previous equation
1257 res <- step (adaptState gst) stt
1264 FL.Partial fs1 -> go SPEC s fs1
1265 FL.Done b -> return $ Yield b (GroupingInit s)
1268 return $ Yield r (GroupingInitWith s x)
1269 Skip s -> go SPEC s acc
1270 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1271 stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1272 stepOuter _ GroupingDone = return Stop
1274{-# INLINE_NORMAL groupsRollingBy #-}
1275groupsRollingBy :: Monad m
1280groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
1281 Stream stepOuter (GroupingInit state)
1285 {-# INLINE_LATE stepOuter #-}
1286 stepOuter _ (GroupingInit st) = do
1287 -- XXX Note that if the stream stops without yielding a single element
1288 -- in the group we discard the "initial" effect.
1292 FL.Partial fs -> Skip $ GroupingDo st fs
1293 FL.Done fb -> Yield fb $ GroupingInit st
1294 stepOuter gst (GroupingDo st fs) = do
1295 res <- step (adaptState gst) st
1300 FL.Partial fs1 -> go SPEC x s fs1
1301 FL.Done fb -> return $ Yield fb (GroupingInit s)
1302 Skip s -> return $ Skip $ GroupingDo s fs
1307 go !_ prev stt !acc = do
1308 res <- step (adaptState gst) stt
1315 FL.Partial fs1 -> go SPEC x s fs1
1316 FL.Done b -> return $ Yield b (GroupingInit s)
1319 return $ Yield r (GroupingInitWith s x)
1320 Skip s -> go SPEC prev s acc
1321 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1322 stepOuter _ (GroupingInitWith st x) = do
1326 FL.Partial s -> Skip $ GroupingDoWith st s x
1327 FL.Done b -> Yield b $ GroupingInitWith st x
1328 stepOuter gst (GroupingDoWith st fs previous) = do
1329 res <- fstep fs previous
1331 FL.Partial s -> go SPEC previous st s
1332 FL.Done b -> return $ Yield b (GroupingInit st)
1336 -- XXX GHC: groupsBy has one less parameter in this go loop and it
1337 -- fuses. However, groupsRollingBy does not fuse, removing the prev
1338 -- parameter makes it fuse. Something needs to be fixed in GHC. The
1339 -- workaround for this is noted in the comments below.
1340 go !_ prev !stt !acc = do
1341 res <- step (adaptState gst) stt
1348 FL.Partial fs1 -> go SPEC x s fs1
1349 FL.Done b -> return $ Yield b (GroupingInit st)
1353 return $ Yield r (GroupingInitWith s x)
1355 -- The code above does not let groupBy fuse. We use the
1356 -- alternative code below instead. Instead of jumping
1357 -- to GroupingInitWith state, we unroll the code of
1358 -- GroupingInitWith state here to help GHC with stream
1365 FL.Partial fsi -> GroupingDoWith s fsi x
1366 FL.Done b -> GroupingYield b (GroupingInit s)
1367 Skip s -> go SPEC prev s acc
1368 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1369 stepOuter _ (GroupingYield r next) = return $ Yield r next
1370 stepOuter _ GroupingDone = return Stop
1372------------------------------------------------------------------------------
1373-- Splitting - by a predicate
1374------------------------------------------------------------------------------
1376data WordsByState st fs b
1380 | WordsByYield !b (WordsByState st fs b)
1382{-# INLINE_NORMAL wordsBy #-}
1383wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1384wordsBy predicate (Fold fstep initial done) (Stream step state) =
1385 Stream stepOuter (WordsByInit state)
1389 {-# INLINE_LATE stepOuter #-}
1390 stepOuter _ (WordsByInit st) = do
1394 FL.Partial s -> Skip $ WordsByDo st s
1395 FL.Done b -> Yield b (WordsByInit st)
1397 stepOuter gst (WordsByDo st fs) = do
1398 res <- step (adaptState gst) st
1406 FL.Partial fs1 -> Skip $ WordsByDo s fs1
1407 FL.Done b -> Yield b (WordsByInit s)
1411 FL.Partial fs1 -> go SPEC s fs1
1412 FL.Done b -> return $ Yield b (WordsByInit s)
1413 Skip s -> return $ Skip $ WordsByDo s fs
1419 res <- step (adaptState gst) stt
1426 return $ Yield r (WordsByInit s)
1428 -- The above code does not fuse well. Need to check why
1429 -- GHC is not able to simplify it well. Using the code
1430 -- below, instead of jumping through the WordsByInit
1431 -- state always, we directly go to WordsByDo state in
1432 -- the common case of Partial.
1438 FL.Partial fs1 -> WordsByDo s fs1
1439 FL.Done b -> WordsByYield b (WordsByInit s)
1443 FL.Partial fs1 -> go SPEC s fs1
1444 FL.Done b -> return $ Yield b (WordsByInit s)
1445 Skip s -> go SPEC s acc
1446 Stop -> done acc >>= \r -> return $ Yield r WordsByDone
1448 stepOuter _ WordsByDone = return Stop
1450 stepOuter _ (WordsByYield b next) = return $ Yield b next
1452------------------------------------------------------------------------------
1453-- Splitting on a sequence
1454------------------------------------------------------------------------------
1456-- String search algorithms:
1457-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1460-- TODO can we unify the splitting operations using a splitting configuration
1461-- like in the split package.
1463data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1464data SplitOptions = SplitOptions
1465 { style :: SplitStyle
1466 , withSep :: Bool -- ^ keep the separators in output
1467 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1468 -- , trimHead :: Bool -- ^ drop blank at head
1469 -- , trimTail :: Bool -- ^ drop blank at tail
1473-- XXX using "fs" as the last arg in Constructors may simplify the code a bit,
1474-- because we can use the constructor directly without having to create "jump"
1476{-# ANN type SplitOnSeqState Fuse #-}
1477data SplitOnSeqState rb rh ck w fs s b x =
1479 | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1482 | SplitOnSeqEmpty !fs s
1484 | SplitOnSeqSingle !fs s x
1486 | SplitOnSeqWordInit !fs s
1487 | SplitOnSeqWordLoop !w s !fs
1488 | SplitOnSeqWordDone Int !fs !w
1490 | SplitOnSeqKRInit Int !fs s rb !rh
1491 | SplitOnSeqKRLoop fs s rb !rh !ck
1492 | SplitOnSeqKRCheck fs s rb !rh
1493 | SplitOnSeqKRDone Int !fs rb !rh
1495 | SplitOnSeqReinit (fs -> SplitOnSeqState rb rh ck w fs s b x)
1497{-# INLINE_NORMAL splitOnSeq #-}
1499 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1504splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1505 Stream stepOuter SplitOnSeqInit
1509 patLen = A.length patArr
1510 maxIndex = patLen - 1
1511 elemBits = sizeOf (undefined :: a) * 8
1513 -- For word pattern case
1515 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1518 elemMask = (1 `shiftL` elemBits) - 1
1521 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1523 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1525 -- For Rabin-Karp search
1526 k = 2891336453 :: Word32
1529 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1531 deltaCksum cksum old new =
1532 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1534 -- XXX shall we use a random starting hash or 1 instead of 0?
1535 patHash = A.foldl' addCksum 0 patArr
1537 skip = return . Skip
1539 nextAfterInit nextGen stepRes =
1541 FL.Partial s -> nextGen s
1542 FL.Done b -> SplitOnSeqYield b (SplitOnSeqReinit nextGen)
1544 {-# INLINE yieldProceed #-}
1545 yieldProceed nextGen fs =
1546 initial >>= skip . SplitOnSeqYield fs . nextAfterInit nextGen
1548 {-# INLINE_LATE stepOuter #-}
1549 stepOuter _ SplitOnSeqInit = do
1554 then return $ Skip $ SplitOnSeqEmpty acc state
1557 pat <- liftIO $ A.unsafeIndexIO patArr 0
1558 return $ Skip $ SplitOnSeqSingle acc state pat
1559 else if sizeOf (undefined :: a) * patLen
1560 <= sizeOf (undefined :: Word)
1561 then return $ Skip $ SplitOnSeqWordInit acc state
1563 (rb, rhead) <- liftIO $ RB.new patLen
1564 skip $ SplitOnSeqKRInit 0 acc state rb rhead
1565 FL.Done b -> skip $ SplitOnSeqYield b SplitOnSeqInit
1567 stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1569 ---------------------------
1571 ---------------------------
1573 stepOuter _ (SplitOnSeqReinit nextGen) =
1574 initial >>= skip . nextAfterInit nextGen
1576 ---------------------------
1578 ---------------------------
1580 stepOuter gst (SplitOnSeqEmpty acc st) = do
1581 res <- step (adaptState gst) st
1587 FL.Partial acc1 -> done acc1
1588 FL.Done b -> return b
1589 let jump c = SplitOnSeqEmpty c s
1590 in yieldProceed jump b1
1591 Skip s -> skip (SplitOnSeqEmpty acc s)
1598 stepOuter _ SplitOnSeqDone = return Stop
1604 stepOuter gst (SplitOnSeqSingle fs st pat) = do
1605 res <- step (adaptState gst) st
1608 let jump c = SplitOnSeqSingle c s pat
1610 then done fs >>= yieldProceed jump
1614 FL.Partial fs1 -> skip $ jump fs1
1615 FL.Done b -> yieldProceed jump b
1616 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1619 return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1621 ---------------------------
1622 -- Short Pattern - Shift Or
1623 ---------------------------
1625 stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1627 skip $ SplitOnSeqYield r SplitOnSeqDone
1628 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1629 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1630 r <- fstep fs (toEnum $ fromIntegral old)
1632 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1634 let jump c = SplitOnSeqWordDone (n - 1) c wrd
1637 stepOuter gst (SplitOnSeqWordInit fs st0) =
1643 go !_ !idx !wrd !st = do
1644 res <- step (adaptState gst) st
1647 let wrd1 = addToWord wrd x
1650 if wrd1 .&. wordMask == wordPat
1652 let jump c = SplitOnSeqWordInit c s
1653 done fs >>= yieldProceed jump
1654 else skip $ SplitOnSeqWordLoop wrd1 s fs
1655 else go SPEC (idx + 1) wrd1 s
1656 Skip s -> go SPEC idx wrd s
1659 then skip $ SplitOnSeqWordDone idx fs wrd
1662 skip $ SplitOnSeqYield r SplitOnSeqDone
1664 stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1665 go SPEC wrd0 st0 fs0
1670 go !_ !wrd !st !fs = do
1671 res <- step (adaptState gst) st
1674 let jump c = SplitOnSeqWordInit c s
1675 wrd1 = addToWord wrd x
1676 old = (wordMask .&. wrd)
1677 `shiftR` (elemBits * (patLen - 1))
1678 r <- fstep fs (toEnum $ fromIntegral old)
1680 FL.Partial fs1 -> do
1681 if wrd1 .&. wordMask == wordPat
1682 then done fs1 >>= yieldProceed jump
1683 else go SPEC wrd1 s fs1
1684 FL.Done b -> yieldProceed jump b
1685 Skip s -> go SPEC wrd s fs
1686 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1688 -------------------------------
1689 -- General Pattern - Karp Rabin
1690 -------------------------------
1692 stepOuter gst (SplitOnSeqKRInit idx fs st rb rh) = do
1693 res <- step (adaptState gst) st
1696 rh1 <- liftIO $ RB.unsafeInsert rb rh x
1699 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1700 let !ringHash = fold addCksum 0 rb
1701 if ringHash == patHash
1702 then skip $ SplitOnSeqKRCheck fs s rb rh1
1703 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1704 else skip $ SplitOnSeqKRInit (idx + 1) fs s rb rh1
1705 Skip s -> skip $ SplitOnSeqKRInit idx fs s rb rh
1707 skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
1709 -- XXX The recursive "go" is more efficient than the state based recursion
1710 -- code commented out below. Perhaps its more efficient because of
1711 -- factoring out "rb" outside the loop.
1713 stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
1714 go SPEC fs0 st0 rh0 cksum0
1718 go !_ !fs !st !rh !cksum = do
1719 res <- step (adaptState gst) st
1722 old <- liftIO $ peek rh
1723 let cksum1 = deltaCksum cksum old x
1726 FL.Partial fs1 -> do
1727 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1728 if cksum1 == patHash
1729 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1730 else go SPEC fs1 s rh1 cksum1
1732 let rst = RB.startOf rb
1733 jump c = SplitOnSeqKRInit 0 c s rb rst
1735 Skip s -> go SPEC fs s rh cksum
1736 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1738 -- XXX The following code is 5 times slower compared to the recursive loop
1739 -- based code above. Need to investigate why. One possibility is that the
1740 -- go loop above does not thread around the ring buffer (rb). This code may
1741 -- be causing the state to bloat and getting allocated on each iteration.
1742 -- We can check the cmm/asm code to confirm. If so a good GHC solution to
1743 -- such problem is needed. One way to avoid this could be to use unboxed
1746 stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
1747 res <- step (adaptState gst) st
1750 old <- liftIO $ peek rh
1751 let cksum1 = deltaCksum cksum old x
1753 if (cksum1 == patHash)
1756 skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
1758 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1759 skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
1760 Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
1761 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1764 stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
1765 if RB.unsafeEqArray rb rh patArr
1768 let rst = RB.startOf rb
1769 jump c = SplitOnSeqKRInit 0 c st rb rst
1771 else skip $ SplitOnSeqKRLoop fs st rb rh patHash
1773 stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
1775 skip $ SplitOnSeqYield r SplitOnSeqDone
1776 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1777 old <- liftIO $ peek rh
1778 let rh1 = RB.advance rb rh
1781 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
1783 let jump c = SplitOnSeqKRDone (n - 1) c rb rh1
1786{-# ANN type SplitOnSuffixSeqState Fuse #-}
1787data SplitOnSuffixSeqState rb rh ck w fs s b x =
1788 SplitOnSuffixSeqInit
1789 | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
1790 | SplitOnSuffixSeqDone
1792 | SplitOnSuffixSeqEmpty !fs s
1794 | SplitOnSuffixSeqSingleInit !fs s x
1795 | SplitOnSuffixSeqSingle !fs s x
1797 | SplitOnSuffixSeqWordInit !fs s
1798 | SplitOnSuffixSeqWordLoop !w s !fs
1799 | SplitOnSuffixSeqWordDone Int !fs !w
1801 | SplitOnSuffixSeqKRInit Int !fs s rb !rh
1802 | SplitOnSuffixSeqKRInit1 !fs s rb !rh
1803 | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
1804 | SplitOnSuffixSeqKRCheck fs s rb !rh
1805 | SplitOnSuffixSeqKRDone Int !fs rb !rh
1807 | SplitOnSuffixSeqReinit
1808 (fs -> SplitOnSuffixSeqState rb rh ck w fs s b x)
1810{-# INLINE_NORMAL splitOnSuffixSeq #-}
1812 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1818splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
1819 Stream stepOuter SplitOnSuffixSeqInit
1823 patLen = A.length patArr
1824 maxIndex = patLen - 1
1825 elemBits = sizeOf (undefined :: a) * 8
1827 -- For word pattern case
1829 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1832 elemMask = (1 `shiftL` elemBits) - 1
1835 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1837 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1839 nextAfterInit nextGen stepRes =
1841 FL.Partial s -> nextGen s
1843 SplitOnSuffixSeqYield b (SplitOnSuffixSeqReinit nextGen)
1845 {-# INLINE yieldProceed #-}
1846 yieldProceed nextGen fs =
1847 initial >>= skip . SplitOnSuffixSeqYield fs . nextAfterInit nextGen
1849 -- For single element pattern case
1850 {-# INLINE processYieldSingle #-}
1851 processYieldSingle pat x s fs = do
1852 let jump c = SplitOnSuffixSeqSingleInit c s pat
1855 r <- if withSep then fstep fs x else return $ FL.Partial fs
1858 FL.Partial fs1 -> done fs1
1859 FL.Done b -> return b
1860 yieldProceed jump b1
1864 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
1865 FL.Done b -> yieldProceed jump b
1867 -- For Rabin-Karp search
1868 k = 2891336453 :: Word32
1871 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1873 deltaCksum cksum old new =
1874 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1876 -- XXX shall we use a random starting hash or 1 instead of 0?
1877 patHash = A.foldl' addCksum 0 patArr
1879 skip = return . Skip
1881 {-# INLINE_LATE stepOuter #-}
1882 stepOuter _ SplitOnSuffixSeqInit = do
1887 then skip $ SplitOnSuffixSeqEmpty fs state
1890 pat <- liftIO $ A.unsafeIndexIO patArr 0
1891 skip $ SplitOnSuffixSeqSingleInit fs state pat
1892 else if sizeOf (undefined :: a) * patLen
1893 <= sizeOf (undefined :: Word)
1894 then skip $ SplitOnSuffixSeqWordInit fs state
1896 (rb, rhead) <- liftIO $ RB.new patLen
1897 skip $ SplitOnSuffixSeqKRInit 0 fs state rb rhead
1898 FL.Done fb -> skip $ SplitOnSuffixSeqYield fb SplitOnSuffixSeqInit
1900 stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
1902 ---------------------------
1904 ---------------------------
1906 stepOuter _ (SplitOnSuffixSeqReinit nextGen) =
1907 initial >>= skip . nextAfterInit nextGen
1909 ---------------------------
1911 ---------------------------
1913 stepOuter gst (SplitOnSuffixSeqEmpty acc st) = do
1914 res <- step (adaptState gst) st
1917 let jump c = SplitOnSuffixSeqEmpty c s
1921 FL.Partial fs -> done fs
1922 FL.Done b -> return b
1923 yieldProceed jump b1
1924 Skip s -> skip (SplitOnSuffixSeqEmpty acc s)
1931 stepOuter _ SplitOnSuffixSeqDone = return Stop
1937 stepOuter gst (SplitOnSuffixSeqSingleInit fs st pat) = do
1938 res <- step (adaptState gst) st
1940 Yield x s -> processYieldSingle pat x s fs
1941 Skip s -> skip $ SplitOnSuffixSeqSingleInit fs s pat
1944 stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
1945 res <- step (adaptState gst) st
1947 Yield x s -> processYieldSingle pat x s fs
1948 Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
1951 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
1953 ---------------------------
1954 -- Short Pattern - Shift Or
1955 ---------------------------
1957 stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
1959 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
1960 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
1961 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1962 r <- fstep fs (toEnum $ fromIntegral old)
1964 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
1966 let jump c = SplitOnSuffixSeqWordDone (n - 1) c wrd
1969 stepOuter gst (SplitOnSuffixSeqWordInit fs0 st0) = do
1970 res <- step (adaptState gst) st0
1973 let wrd = addToWord 0 x
1974 r <- if withSep then fstep fs0 x else return $ FL.Partial fs0
1976 FL.Partial fs1 -> go SPEC 1 wrd s fs1
1978 let jump c = SplitOnSuffixSeqWordInit c s
1980 Skip s -> skip (SplitOnSuffixSeqWordInit fs0 s)
1986 go !_ !idx !wrd !st !fs = do
1987 res <- step (adaptState gst) st
1990 let jump c = SplitOnSuffixSeqWordInit c s
1991 let wrd1 = addToWord wrd x
1992 r <- if withSep then fstep fs x else return $ FL.Partial fs
1996 then go SPEC (idx + 1) wrd1 s fs1
1997 else if wrd1 .&. wordMask /= wordPat
1998 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
1999 else do done fs >>= yieldProceed jump
2000 FL.Done b -> yieldProceed jump b
2001 Skip s -> go SPEC idx wrd s fs
2002 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2004 stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2005 go SPEC wrd0 st0 fs0
2010 go !_ !wrd !st !fs = do
2011 res <- step (adaptState gst) st
2014 let jump c = SplitOnSuffixSeqWordInit c s
2015 wrd1 = addToWord wrd x
2016 old = (wordMask .&. wrd)
2017 `shiftR` (elemBits * (patLen - 1))
2021 else fstep fs (toEnum $ fromIntegral old)
2024 if wrd1 .&. wordMask == wordPat
2025 then done fs1 >>= yieldProceed jump
2026 else go SPEC wrd1 s fs1
2027 FL.Done b -> yieldProceed jump b
2028 Skip s -> go SPEC wrd s fs
2030 if wrd .&. wordMask == wordPat
2035 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2036 else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2038 -------------------------------
2039 -- General Pattern - Karp Rabin
2040 -------------------------------
2042 stepOuter gst (SplitOnSuffixSeqKRInit idx0 fs st0 rb rh0) = do
2043 res <- step (adaptState gst) st0
2046 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2047 r <- if withSep then fstep fs x else return $ FL.Partial fs
2050 skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2052 let rst = RB.startOf rb
2053 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2055 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 fs s rb rh0
2058 stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2059 go SPEC 1 rh0 st0 fs0
2063 go !_ !idx !rh st !fs = do
2064 res <- step (adaptState gst) st
2067 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2068 r <- if withSep then fstep fs x else return $ FL.Partial fs
2072 then go SPEC (idx + 1) rh1 s fs1
2074 let fold = RB.unsafeFoldRing (RB.ringBound rb)
2075 !ringHash = fold addCksum 0 rb
2076 in if ringHash == patHash
2077 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2078 else SplitOnSuffixSeqKRLoop
2079 fs1 s rb rh1 ringHash
2081 let rst = RB.startOf rb
2082 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2084 Skip s -> go SPEC idx rh s fs
2086 -- do not issue a blank segment when we end at pattern
2087 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2092 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2093 else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2095 stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2096 go SPEC fs0 st0 rh0 cksum0
2100 go !_ !fs !st !rh !cksum = do
2101 res <- step (adaptState gst) st
2104 old <- liftIO $ peek rh
2105 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2106 let cksum1 = deltaCksum cksum old x
2107 r <- if withSep then fstep fs x else fstep fs old
2110 if (cksum1 /= patHash)
2111 then go SPEC fs1 s rh1 cksum1
2112 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2114 let rst = RB.startOf rb
2115 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2117 Skip s -> go SPEC fs s rh cksum
2119 if RB.unsafeEqArray rb rh patArr
2124 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2125 else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2127 stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2128 if RB.unsafeEqArray rb rh patArr
2131 let rst = RB.startOf rb
2132 jump c = SplitOnSuffixSeqKRInit 0 c st rb rst
2134 else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2136 stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2138 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2139 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2140 old <- liftIO $ peek rh
2141 let rh1 = RB.advance rb rh
2144 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2146 let jump c = SplitOnSuffixSeqKRDone (n - 1) c rb rh1
2149------------------------------------------------------------------------------
2150-- Nested Container Transformation
2151------------------------------------------------------------------------------
2153{-# ANN type SplitState Fuse #-}
2154data SplitState s arr
2156 | SplitBuffering s arr
2157 | SplitSplitting s arr
2158 | SplitYielding arr (SplitState s arr)
2161-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2162-- split using a splitBy like combinator. The Fold would consume upto the
2163-- separator and return any leftover which can then be fed to the next fold.
2165-- We can revisit this once we have partial folds/parsers.
2167-- | Performs infix separator style splitting.
2168{-# INLINE_NORMAL splitInnerBy #-}
2171 => (f a -> m (f a, Maybe (f a))) -- splitter
2172 -> (f a -> f a -> m (f a)) -- joiner
2175splitInnerBy splitter joiner (Stream step1 state1) =
2176 (Stream step (SplitInitial state1))
2180 {-# INLINE_LATE step #-}
2181 step gst (SplitInitial st) = do
2185 (x1, mx2) <- splitter x
2186 return $ case mx2 of
2187 Nothing -> Skip (SplitBuffering s x1)
2188 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2189 Skip s -> return $ Skip (SplitInitial s)
2190 Stop -> return $ Stop
2192 step gst (SplitBuffering st buf) = do
2196 (x1, mx2) <- splitter x
2197 buf' <- joiner buf x1
2198 return $ case mx2 of
2199 Nothing -> Skip (SplitBuffering s buf')
2200 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2201 Skip s -> return $ Skip (SplitBuffering s buf)
2202 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2204 step _ (SplitSplitting st buf) = do
2205 (x1, mx2) <- splitter buf
2206 return $ case mx2 of
2207 Nothing -> Skip $ SplitBuffering st x1
2208 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2210 step _ (SplitYielding x next) = return $ Yield x next
2211 step _ SplitFinishing = return $ Stop
2213-- | Performs infix separator style splitting.
2214{-# INLINE_NORMAL splitInnerBySuffix #-}
2216 :: (Monad m, Eq (f a), Monoid (f a))
2217 => (f a -> m (f a, Maybe (f a))) -- splitter
2218 -> (f a -> f a -> m (f a)) -- joiner
2221splitInnerBySuffix splitter joiner (Stream step1 state1) =
2222 (Stream step (SplitInitial state1))
2226 {-# INLINE_LATE step #-}
2227 step gst (SplitInitial st) = do
2231 (x1, mx2) <- splitter x
2232 return $ case mx2 of
2233 Nothing -> Skip (SplitBuffering s x1)
2234 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2235 Skip s -> return $ Skip (SplitInitial s)
2236 Stop -> return $ Stop
2238 step gst (SplitBuffering st buf) = do
2242 (x1, mx2) <- splitter x
2243 buf' <- joiner buf x1
2244 return $ case mx2 of
2245 Nothing -> Skip (SplitBuffering s buf')
2246 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2247 Skip s -> return $ Skip (SplitBuffering s buf)
2251 else Skip (SplitYielding buf SplitFinishing)
2253 step _ (SplitSplitting st buf) = do
2254 (x1, mx2) <- splitter buf
2255 return $ case mx2 of
2256 Nothing -> Skip $ SplitBuffering st x1
2257 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2259 step _ (SplitYielding x next) = return $ Yield x next
2260 step _ SplitFinishing = return Stop
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list