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