on e7d2a73 help sign in
3948 lines 139 kB history raw
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE RecordWildCards #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE ViewPatterns #-}
12{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE MagicHash #-}
15#if __GLASGOW_HASKELL__ >= 801
16{-# LANGUAGE TypeApplications #-}
17#endif
19#include "inline.hs"
21-- |
22-- Module : Streamly.Streams.StreamD
23-- Copyright : (c) 2018 Harendra Kumar
24-- Copyright : (c) Roman Leshchinskiy 2008-2010
25-- Copyright : (c) The University of Glasgow, 2009
26-- Copyright : (c) Bjoern Hoehrmann 2008-2009
27--
28-- License : BSD3
29-- Maintainer : streamly@composewell.com
30-- Stability : experimental
31-- Portability : GHC
32--
33-- Direct style re-implementation of CPS style stream in StreamK module. The
34-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
35-- to INLINE and fuse direct style better, providing better performance than
36-- CPS implementation.
37--
38-- @
39-- import qualified Streamly.Streams.StreamD as D
40-- @
42-- Some of the functions in this file have been adapted from the vector
43-- library, https://hackage.haskell.org/package/vector.
45module Streamly.Streams.StreamD
46 (
47 -- * The stream type
48 Step (..)
49 , Stream (..)
51 -- * Construction
52 , nil
53 , nilM
54 , cons
56 -- * Deconstruction
57 , uncons
59 -- * Generation
60 -- ** Unfolds
61 , unfoldr
62 , unfoldrM
63 , unfold
65 -- ** Specialized Generation
66 -- | Generate a monadic stream from a seed.
67 , repeat
68 , repeatM
69 , replicate
70 , replicateM
71 , fromIndices
72 , fromIndicesM
73 , generate
74 , generateM
76 -- ** Enumerations
77 , enumerateFromStepIntegral
78 , enumerateFromIntegral
79 , enumerateFromThenIntegral
80 , enumerateFromToIntegral
81 , enumerateFromThenToIntegral
83 , enumerateFromStepNum
84 , numFrom
85 , numFromThen
86 , enumerateFromToFractional
87 , enumerateFromThenToFractional
89 -- ** Conversions
90 -- | Transform an input structure into a stream.
91 -- | Direct style stream does not support @fromFoldable@.
92 , yield
93 , yieldM
94 , fromList
95 , fromListM
96 , fromStreamK
97 , fromStreamD
99 -- * Elimination
100 -- ** General Folds
101 , foldrS
102 , foldrT
103 , foldrM
104 , foldrMx
105 , foldr
106 , foldr1
108 , foldl'
109 , foldlM'
110 , foldlS
111 , foldlT
112 , reverse
113 , reverse'
115 , foldlx'
116 , foldlMx'
118 -- ** Specialized Folds
119 , tap
120 , drain
121 , null
122 , head
123 , tail
124 , last
125 , elem
126 , notElem
127 , all
128 , any
129 , maximum
130 , maximumBy
131 , minimum
132 , minimumBy
133 , findIndices
134 , lookup
135 , findM
136 , find
137 , (!!)
139 -- ** Flattening nested streams
140 , concatMapM
141 , concatMap
142 , ConcatMapUState (..)
143 , concatMapU
144 , ConcatUnfoldInterleaveState (..)
145 , concatUnfoldInterleave
146 , concatUnfoldRoundrobin
147 , AppendState(..)
148 , append
149 , InterleaveState(..)
150 , interleave
151 , interleaveMin
152 , interleaveSuffix
153 , interleaveInfix
154 , roundRobin -- interleaveFair?/ParallelFair
155 , gintercalateSuffix
156 , interposeSuffix
157 , gintercalate
158 , interpose
160 -- ** Grouping
161 , groupsOf
162 , groupsBy
163 , groupsRollingBy
165 -- ** Splitting
166 , splitBy
167 , splitSuffixBy
168 , wordsBy
169 , splitSuffixBy'
171 , splitOn
172 , splitSuffixOn
174 , splitInnerBy
175 , splitInnerBySuffix
177 -- ** Substreams
178 , isPrefixOf
179 , isSubsequenceOf
180 , stripPrefix
182 -- ** Map and Fold
183 , mapM_
185 -- ** Conversions
186 -- | Transform a stream into another type.
187 , toList
188 , toListRev
189 , toStreamK
190 , toStreamD
192 , hoist
193 , generally
195 , liftInner
196 , runReaderT
197 , evalStateT
198 , runStateT
200 -- * Transformation
201 , transform
203 -- ** By folding (scans)
204 , scanlM'
205 , scanl'
206 , scanlM
207 , scanl
208 , scanl1M'
209 , scanl1'
210 , scanl1M
211 , scanl1
213 , prescanl'
214 , prescanlM'
216 , postscanl
217 , postscanlM
218 , postscanl'
219 , postscanlM'
221 , postscanlx'
222 , postscanlMx'
223 , scanlMx'
224 , scanlx'
226 -- * Filtering
227 , filter
228 , filterM
229 , uniq
230 , take
231 , takeWhile
232 , takeWhileM
233 , drop
234 , dropWhile
235 , dropWhileM
237 -- * Mapping
238 , map
239 , mapM
240 , sequence
242 -- * Inserting
243 , intersperseM
244 , intersperse
245 , intersperseSuffix
246 , insertBy
248 -- * Deleting
249 , deleteBy
251 -- ** Map and Filter
252 , mapMaybe
253 , mapMaybeM
255 -- * Zipping
256 , indexed
257 , indexedR
258 , zipWith
259 , zipWithM
261 -- * Comparisons
262 , eqBy
263 , cmpBy
265 -- * Merging
266 , mergeBy
267 , mergeByM
269 -- * Transformation comprehensions
270 , the
272 -- * Exceptions
273 , gbracket
274 , before
275 , after
276 , bracket
277 , onException
278 , finally
279 , handle
281 -- * UTF8 Encoding / Decoding transformations.
282 , DecodeError(..)
283 , DecodeState
284 , CodePoint
285 , decodeUtf8
286 , encodeUtf8
287 , decodeUtf8Lenient
288 , decodeUtf8Either
289 , resumeDecodeUtf8Either
290 , decodeUtf8Arrays
291 , decodeUtf8ArraysLenient
292 )
293where
295import Control.Exception (Exception, SomeException)
296import Control.Monad (void)
297import Control.Monad.Catch (MonadCatch)
298import Control.Monad.IO.Class (MonadIO(..))
299import Control.Monad.Reader (ReaderT)
300import Control.Monad.State.Strict (StateT)
301import Control.Monad.Trans (MonadTrans(lift))
302import Data.Bits (shiftR, shiftL, (.|.), (.&.))
303import Data.Functor.Identity (Identity(..))
304import Data.Maybe (fromJust, isJust)
305import Data.Word (Word32)
306import Foreign.Ptr (Ptr)
307import Foreign.Storable (Storable(..))
308import GHC.Base (assert, Char(..), unsafeChr, ord)
309import GHC.IO.Encoding.Failure (isSurrogate)
310import GHC.ForeignPtr (ForeignPtr (..))
311import GHC.Ptr (Ptr (..))
312import GHC.Types (SPEC(..))
313import GHC.Word (Word8(..))
314import System.IO.Unsafe (unsafePerformIO)
315import Prelude
316 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
317 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
318 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
319 (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat,
320 reverse)
322import qualified Control.Monad.Catch as MC
323import qualified Control.Monad.Reader as Reader
324import qualified Control.Monad.State.Strict as State
326import Streamly.Internal.Memory.Array.Types (Array(..))
327import Streamly.Internal.Data.Fold.Types (Fold(..))
328import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
329import Streamly.Internal.Data.SVar (MonadAsync, defState, adaptState)
330import Streamly.Internal.Data.Unfold.Types (Unfold(..))
331import Streamly.Internal.Data.Strict (Tuple'(..))
333import Streamly.Internal.Data.Stream.StreamD.Type
335import qualified Streamly.Internal.Data.Pipe.Types as Pipe
336import qualified Streamly.Internal.Memory.Array.Types as A
337import qualified Streamly.Memory.Ring as RB
338import qualified Streamly.Streams.StreamK as K
340import Foreign.Ptr (plusPtr)
341import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
342import Foreign.ForeignPtr (touchForeignPtr)
344------------------------------------------------------------------------------
345-- Construction
346------------------------------------------------------------------------------
348-- | An empty 'Stream'.
349{-# INLINE_NORMAL nil #-}
350nil :: Monad m => Stream m a
351nil = Stream (\_ _ -> return Stop) ()
353-- | An empty 'Stream' with a side effect.
354{-# INLINE_NORMAL nilM #-}
355nilM :: Monad m => m b -> Stream m a
356nilM m = Stream (\_ _ -> m >> return Stop) ()
358{-# INLINE_NORMAL consM #-}
359consM :: Monad m => m a -> Stream m a -> Stream m a
360consM m (Stream step state) = Stream step1 Nothing
361 where
362 {-# INLINE_LATE step1 #-}
363 step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
364 step1 gst (Just st) = do
365 r <- step gst st
366 return $
367 case r of
368 Yield a s -> Yield a (Just s)
369 Skip s -> Skip (Just s)
370 Stop -> Stop
372-- XXX implement in terms of consM?
373-- cons x = consM (return x)
374--
375-- | Can fuse but has O(n^2) complexity.
376{-# INLINE_NORMAL cons #-}
377cons :: Monad m => a -> Stream m a -> Stream m a
378cons x (Stream step state) = Stream step1 Nothing
379 where
380 {-# INLINE_LATE step1 #-}
381 step1 _ Nothing = return $ Yield x (Just state)
382 step1 gst (Just st) = do
383 r <- step gst st
384 return $
385 case r of
386 Yield a s -> Yield a (Just s)
387 Skip s -> Skip (Just s)
388 Stop -> Stop
390-------------------------------------------------------------------------------
391-- Deconstruction
392-------------------------------------------------------------------------------
394-- Does not fuse, has the same performance as the StreamK version.
395{-# INLINE_NORMAL uncons #-}
396uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
397uncons (UnStream step state) = go state
398 where
399 go st = do
400 r <- step defState st
401 case r of
402 Yield x s -> return $ Just (x, Stream step s)
403 Skip s -> go s
404 Stop -> return Nothing
406------------------------------------------------------------------------------
407-- Generation by unfold
408------------------------------------------------------------------------------
410{-# INLINE_NORMAL unfoldrM #-}
411unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
412unfoldrM next state = Stream step state
413 where
414 {-# INLINE_LATE step #-}
415 step _ st = do
416 r <- next st
417 return $ case r of
418 Just (x, s) -> Yield x s
419 Nothing -> Stop
421{-# INLINE_LATE unfoldr #-}
422unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
423unfoldr f = unfoldrM (return . f)
425-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
426--
427{-# INLINE_NORMAL unfold #-}
428unfold :: Monad m => Unfold m a b -> a -> Stream m b
429unfold (Unfold ustep inject) seed = Stream step Nothing
430 where
431 {-# INLINE_LATE step #-}
432 step _ Nothing = inject seed >>= return . Skip . Just
433 step _ (Just st) = do
434 r <- ustep st
435 return $ case r of
436 Yield x s -> Yield x (Just s)
437 Skip s -> Skip (Just s)
438 Stop -> Stop
440------------------------------------------------------------------------------
441-- Specialized Generation
442------------------------------------------------------------------------------
444repeatM :: Monad m => m a -> Stream m a
445repeatM x = Stream (\_ _ -> x >>= \r -> return $ Yield r ()) ()
447repeat :: Monad m => a -> Stream m a
448repeat x = Stream (\_ _ -> return $ Yield x ()) ()
450{-# INLINE_NORMAL replicateM #-}
451replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
452replicateM n p = Stream step n
453 where
454 {-# INLINE_LATE step #-}
455 step _ (i :: Int)
456 | i <= 0 = return Stop
457 | otherwise = do
458 x <- p
459 return $ Yield x (i - 1)
461{-# INLINE_NORMAL replicate #-}
462replicate :: Monad m => Int -> a -> Stream m a
463replicate n x = replicateM n (return x)
465-- This would not work properly for floats, therefore we put an Integral
466-- constraint.
467-- | Can be used to enumerate unbounded integrals. This does not check for
468-- overflow or underflow for bounded integrals.
469{-# INLINE_NORMAL enumerateFromStepIntegral #-}
470enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
471enumerateFromStepIntegral from stride =
472 from `seq` stride `seq` Stream step from
473 where
474 {-# INLINE_LATE step #-}
475 step _ !x = return $ Yield x $! (x + stride)
477-- We are assuming that "to" is constrained by the type to be within
478-- max/min bounds.
479{-# INLINE enumerateFromToIntegral #-}
480enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
481enumerateFromToIntegral from to =
482 takeWhile (<= to) $ enumerateFromStepIntegral from 1
484{-# INLINE enumerateFromIntegral #-}
485enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
486enumerateFromIntegral from = enumerateFromToIntegral from maxBound
488data EnumState a = EnumInit | EnumYield a a a | EnumStop
490{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
491enumerateFromThenToIntegralUp
492 :: (Monad m, Integral a)
493 => a -> a -> a -> Stream m a
494enumerateFromThenToIntegralUp from next to = Stream step EnumInit
495 where
496 {-# INLINE_LATE step #-}
497 step _ EnumInit =
498 return $
499 if to < next
500 then if to < from
501 then Stop
502 else Yield from EnumStop
503 else -- from <= next <= to
504 let stride = next - from
505 in Skip $ EnumYield from stride (to - stride)
507 step _ (EnumYield x stride toMinus) =
508 return $
509 if x > toMinus
510 then Yield x EnumStop
511 else Yield x $ EnumYield (x + stride) stride toMinus
513 step _ EnumStop = return Stop
515{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
516enumerateFromThenToIntegralDn
517 :: (Monad m, Integral a)
518 => a -> a -> a -> Stream m a
519enumerateFromThenToIntegralDn from next to = Stream step EnumInit
520 where
521 {-# INLINE_LATE step #-}
522 step _ EnumInit =
523 return $ if to > next
524 then if to > from
525 then Stop
526 else Yield from EnumStop
527 else -- from >= next >= to
528 let stride = next - from
529 in Skip $ EnumYield from stride (to - stride)
531 step _ (EnumYield x stride toMinus) =
532 return $
533 if x < toMinus
534 then Yield x EnumStop
535 else Yield x $ EnumYield (x + stride) stride toMinus
537 step _ EnumStop = return Stop
539{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
540enumerateFromThenToIntegral
541 :: (Monad m, Integral a)
542 => a -> a -> a -> Stream m a
543enumerateFromThenToIntegral from next to
544 | next >= from = enumerateFromThenToIntegralUp from next to
545 | otherwise = enumerateFromThenToIntegralDn from next to
547{-# INLINE_NORMAL enumerateFromThenIntegral #-}
548enumerateFromThenIntegral
549 :: (Monad m, Integral a, Bounded a)
550 => a -> a -> Stream m a
551enumerateFromThenIntegral from next =
552 if next > from
553 then enumerateFromThenToIntegralUp from next maxBound
554 else enumerateFromThenToIntegralDn from next minBound
556-- For floating point numbers if the increment is less than the precision then
557-- it just gets lost. Therefore we cannot always increment it correctly by just
558-- repeated addition.
559-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
560-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
562-- Instead we accumulate the increment counter and compute the increment
563-- everytime before adding it to the starting number.
564--
565-- This works for Integrals as well as floating point numbers, but
566-- enumerateFromStepIntegral is faster for integrals.
567{-# INLINE_NORMAL enumerateFromStepNum #-}
568enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
569enumerateFromStepNum from stride = Stream step 0
570 where
571 {-# INLINE_LATE step #-}
572 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
574{-# INLINE_NORMAL numFrom #-}
575numFrom :: (Monad m, Num a) => a -> Stream m a
576numFrom from = enumerateFromStepNum from 1
578{-# INLINE_NORMAL numFromThen #-}
579numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
580numFromThen from next = enumerateFromStepNum from (next - from)
582-- We cannot write a general function for Num. The only way to write code
583-- portable between the two is to use a 'Real' constraint and convert between
584-- Fractional and Integral using fromRational which is horribly slow.
585{-# INLINE_NORMAL enumerateFromToFractional #-}
586enumerateFromToFractional
587 :: (Monad m, Fractional a, Ord a)
588 => a -> a -> Stream m a
589enumerateFromToFractional from to =
590 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
592{-# INLINE_NORMAL enumerateFromThenToFractional #-}
593enumerateFromThenToFractional
594 :: (Monad m, Fractional a, Ord a)
595 => a -> a -> a -> Stream m a
596enumerateFromThenToFractional from next to =
597 takeWhile predicate $ numFromThen from next
598 where
599 mid = (next - from) / 2
600 predicate | next >= from = (<= to + mid)
601 | otherwise = (>= to + mid)
603-------------------------------------------------------------------------------
604-- Generation by Conversion
605-------------------------------------------------------------------------------
607{-# INLINE_NORMAL fromIndicesM #-}
608fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
609fromIndicesM gen = Stream step 0
610 where
611 {-# INLINE_LATE step #-}
612 step _ i = do
613 x <- gen i
614 return $ Yield x (i + 1)
616{-# INLINE fromIndices #-}
617fromIndices :: Monad m => (Int -> a) -> Stream m a
618fromIndices gen = fromIndicesM (return . gen)
620{-# INLINE_NORMAL generateM #-}
621generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
622generateM n gen = n `seq` Stream step 0
623 where
624 {-# INLINE_LATE step #-}
625 step _ i | i < n = do
626 x <- gen i
627 return $ Yield x (i + 1)
628 | otherwise = return Stop
630{-# INLINE generate #-}
631generate :: Monad m => Int -> (Int -> a) -> Stream m a
632generate n gen = generateM n (return . gen)
634-- XXX we need the MonadAsync constraint because of a rewrite rule.
635-- | Convert a list of monadic actions to a 'Stream'
636{-# INLINE_LATE fromListM #-}
637fromListM :: MonadAsync m => [m a] -> Stream m a
638fromListM = Stream step
639 where
640 {-# INLINE_LATE step #-}
641 step _ (m:ms) = m >>= \x -> return $ Yield x ms
642 step _ [] = return Stop
644{-# INLINE toStreamD #-}
645toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
646toStreamD = fromStreamK . K.toStream
648{-# INLINE_NORMAL hoist #-}
649hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
650hoist f (Stream step state) = (Stream step' state)
651 where
652 step' gst st = do
653 r <- f $ step (adaptState gst) st
654 return $ case r of
655 Yield x s -> Yield x s
656 Skip s -> Skip s
657 Stop -> Stop
659{-# INLINE_NORMAL generally #-}
660generally :: Monad m => Stream Identity a -> Stream m a
661generally = hoist (return . runIdentity)
663{-# INLINE_NORMAL liftInner #-}
664liftInner :: (Monad m, MonadTrans t, Monad (t m))
665 => Stream m a -> Stream (t m) a
666liftInner (Stream step state) = Stream step' state
667 where
668 step' gst st = do
669 r <- lift $ step (adaptState gst) st
670 return $ case r of
671 Yield x s -> Yield x s
672 Skip s -> Skip s
673 Stop -> Stop
675{-# INLINE_NORMAL runReaderT #-}
676runReaderT :: Monad m => s -> Stream (ReaderT s m) a -> Stream m a
677runReaderT sval (Stream step state) = Stream step' state
678 where
679 step' gst st = do
680 r <- Reader.runReaderT (step (adaptState gst) st) sval
681 return $ case r of
682 Yield x s -> Yield x s
683 Skip s -> Skip s
684 Stop -> Stop
686{-# INLINE_NORMAL evalStateT #-}
687evalStateT :: Monad m => s -> Stream (StateT s m) a -> Stream m a
688evalStateT sval (Stream step state) = Stream step' (state, sval)
689 where
690 step' gst (st, sv) = do
691 (r, sv') <- State.runStateT (step (adaptState gst) st) sv
692 return $ case r of
693 Yield x s -> Yield x (s, sv')
694 Skip s -> Skip (s, sv')
695 Stop -> Stop
697{-# INLINE_NORMAL runStateT #-}
698runStateT :: Monad m => s -> Stream (StateT s m) a -> Stream m (s, a)
699runStateT sval (Stream step state) = Stream step' (state, sval)
700 where
701 step' gst (st, sv) = do
702 (r, sv') <- State.runStateT (step (adaptState gst) st) sv
703 return $ case r of
704 Yield x s -> Yield (sv', x) (s, sv')
705 Skip s -> Skip (s, sv')
706 Stop -> Stop
708------------------------------------------------------------------------------
709-- Elimination by Folds
710------------------------------------------------------------------------------
712------------------------------------------------------------------------------
713-- Right Folds
714------------------------------------------------------------------------------
716{-# INLINE_NORMAL foldr1 #-}
717foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
718foldr1 f m = do
719 r <- uncons m
720 case r of
721 Nothing -> return Nothing
722 Just (h, t) -> fmap Just (foldr f h t)
724------------------------------------------------------------------------------
725-- Left Folds
726------------------------------------------------------------------------------
728{-# INLINE_NORMAL foldlT #-}
729foldlT :: (Monad m, Monad (s m), MonadTrans s)
730 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
731foldlT fstep begin (Stream step state) = go SPEC begin state
732 where
733 go !_ acc st = do
734 r <- lift $ step defState st
735 case r of
736 Yield x s -> go SPEC (fstep acc x) s
737 Skip s -> go SPEC acc s
738 Stop -> acc
740-- Note, this is going to have horrible performance, because of the nature of
741-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
742-- likely be practically unusable.
743{-# INLINE_NORMAL foldlS #-}
744foldlS :: Monad m
745 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
746foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
747 where
748 step' gst (Left (st, acc)) = do
749 r <- step (adaptState gst) st
750 return $ case r of
751 Yield x s -> Skip (Left (s, fstep acc x))
752 Skip s -> Skip (Left (s, acc))
753 Stop -> Skip (Right acc)
755 step' gst (Right (Stream stp stt)) = do
756 r <- stp (adaptState gst) stt
757 return $ case r of
758 Yield x s -> Yield x (Right (Stream stp s))
759 Skip s -> Skip (Right (Stream stp s))
760 Stop -> Stop
762------------------------------------------------------------------------------
763-- Specialized Folds
764------------------------------------------------------------------------------
766-- | Run a streaming composition, discard the results.
767{-# INLINE_LATE drain #-}
768drain :: Monad m => Stream m a -> m ()
769-- drain = foldrM (\_ xs -> xs) (return ())
770drain (Stream step state) = go SPEC state
771 where
772 go !_ st = do
773 r <- step defState st
774 case r of
775 Yield _ s -> go SPEC s
776 Skip s -> go SPEC s
777 Stop -> return ()
779{-# INLINE_NORMAL null #-}
780null :: Monad m => Stream m a -> m Bool
781null m = foldrM (\_ _ -> return False) (return True) m
783{-# INLINE_NORMAL head #-}
784head :: Monad m => Stream m a -> m (Maybe a)
785head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
787-- Does not fuse, has the same performance as the StreamK version.
788{-# INLINE_NORMAL tail #-}
789tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
790tail (UnStream step state) = go state
791 where
792 go st = do
793 r <- step defState st
794 case r of
795 Yield _ s -> return (Just $ Stream step s)
796 Skip s -> go s
797 Stop -> return Nothing
799-- XXX will it fuse? need custom impl?
800{-# INLINE_NORMAL last #-}
801last :: Monad m => Stream m a -> m (Maybe a)
802last = foldl' (\_ y -> Just y) Nothing
804{-# INLINE_NORMAL elem #-}
805elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
806-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
807elem e (Stream step state) = go state
808 where
809 go st = do
810 r <- step defState st
811 case r of
812 Yield x s
813 | x == e -> return True
814 | otherwise -> go s
815 Skip s -> go s
816 Stop -> return False
818{-# INLINE_NORMAL notElem #-}
819notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
820notElem e s = fmap not (elem e s)
822{-# INLINE_NORMAL all #-}
823all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
824-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
825all p (Stream step state) = go state
826 where
827 go st = do
828 r <- step defState st
829 case r of
830 Yield x s
831 | p x -> go s
832 | otherwise -> return False
833 Skip s -> go s
834 Stop -> return True
836{-# INLINE_NORMAL any #-}
837any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
838-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
839any p (Stream step state) = go state
840 where
841 go st = do
842 r <- step defState st
843 case r of
844 Yield x s
845 | p x -> return True
846 | otherwise -> go s
847 Skip s -> go s
848 Stop -> return False
850{-# INLINE_NORMAL maximum #-}
851maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
852maximum (Stream step state) = go Nothing state
853 where
854 go Nothing st = do
855 r <- step defState st
856 case r of
857 Yield x s -> go (Just x) s
858 Skip s -> go Nothing s
859 Stop -> return Nothing
860 go (Just acc) st = do
861 r <- step defState st
862 case r of
863 Yield x s
864 | acc <= x -> go (Just x) s
865 | otherwise -> go (Just acc) s
866 Skip s -> go (Just acc) s
867 Stop -> return (Just acc)
869{-# INLINE_NORMAL maximumBy #-}
870maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
871maximumBy cmp (Stream step state) = go Nothing state
872 where
873 go Nothing st = do
874 r <- step defState st
875 case r of
876 Yield x s -> go (Just x) s
877 Skip s -> go Nothing s
878 Stop -> return Nothing
879 go (Just acc) st = do
880 r <- step defState st
881 case r of
882 Yield x s -> case cmp acc x of
883 GT -> go (Just acc) s
884 _ -> go (Just x) s
885 Skip s -> go (Just acc) s
886 Stop -> return (Just acc)
888{-# INLINE_NORMAL minimum #-}
889minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
890minimum (Stream step state) = go Nothing state
891 where
892 go Nothing st = do
893 r <- step defState st
894 case r of
895 Yield x s -> go (Just x) s
896 Skip s -> go Nothing s
897 Stop -> return Nothing
898 go (Just acc) st = do
899 r <- step defState st
900 case r of
901 Yield x s
902 | acc <= x -> go (Just acc) s
903 | otherwise -> go (Just x) s
904 Skip s -> go (Just acc) s
905 Stop -> return (Just acc)
907{-# INLINE_NORMAL minimumBy #-}
908minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
909minimumBy cmp (Stream step state) = go Nothing state
910 where
911 go Nothing st = do
912 r <- step defState st
913 case r of
914 Yield x s -> go (Just x) s
915 Skip s -> go Nothing s
916 Stop -> return Nothing
917 go (Just acc) st = do
918 r <- step defState st
919 case r of
920 Yield x s -> case cmp acc x of
921 GT -> go (Just x) s
922 _ -> go (Just acc) s
923 Skip s -> go (Just acc) s
924 Stop -> return (Just acc)
926{-# INLINE_NORMAL (!!) #-}
927(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
928(Stream step state) !! i = go i state
929 where
930 go n st = do
931 r <- step defState st
932 case r of
933 Yield x s | n < 0 -> return Nothing
934 | n == 0 -> return $ Just x
935 | otherwise -> go (n - 1) s
936 Skip s -> go n s
937 Stop -> return Nothing
939{-# INLINE_NORMAL lookup #-}
940lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
941lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
942 (return Nothing) m
944{-# INLINE_NORMAL findM #-}
945findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
946findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
947 (return Nothing) m
949{-# INLINE find #-}
950find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
951find p = findM (return . p)
953{-# INLINE_NORMAL findIndices #-}
954findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
955findIndices p (Stream step state) = Stream step' (state, 0)
956 where
957 {-# INLINE_LATE step' #-}
958 step' gst (st, i) = do
959 r <- step (adaptState gst) st
960 return $ case r of
961 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
962 Skip s -> Skip (s, i+1)
963 Stop -> Stop
965{-# INLINE toListRev #-}
966toListRev :: Monad m => Stream m a -> m [a]
967toListRev = foldl' (flip (:)) []
969-- We can implement reverse as:
970--
971-- > reverse = foldlS (flip cons) nil
972--
973-- However, this implementation is unusable because of the horrible performance
974-- of cons. So we just convert it to a list first and then stream from the
975-- list.
976--
977-- XXX Maybe we can use an Array instead of a list here?
978{-# INLINE_NORMAL reverse #-}
979reverse :: Monad m => Stream m a -> Stream m a
980reverse m = Stream step Nothing
981 where
982 {-# INLINE_LATE step #-}
983 step _ Nothing = do
984 xs <- toListRev m
985 return $ Skip (Just xs)
986 step _ (Just (x:xs)) = return $ Yield x (Just xs)
987 step _ (Just []) = return Stop
989-- Much faster reverse for Storables
990{-# INLINE_NORMAL reverse' #-}
991reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
992{-
993-- This commented implementation copies the whole stream into one single array
994-- and then streams from that array, this is 3-4x faster than the chunked code
995-- that follows. Though this could be problematic due to unbounded large
996-- allocations. We need to figure out why the chunked code is slower and if we
997-- can optimize the chunked code to work as fast as this one. It may be a
998-- fusion issue?
999import Foreign.ForeignPtr (touchForeignPtr)
1000import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1001import Foreign.Ptr (Ptr, plusPtr)
1002reverse' m = Stream step Nothing
1003 where
1004 {-# INLINE_LATE step #-}
1005 step _ Nothing = do
1006 arr <- A.fromStreamD m
1007 let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1008 return $ Skip $ Just (aStart arr, p)
1010 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1012 step _ (Just (start, p)) = do
1013 let !x = A.unsafeInlineIO $ do
1014 r <- peek p
1015 touchForeignPtr start
1016 return r
1017 next = p `plusPtr` negate (sizeOf (undefined :: a))
1018 return $ Yield x (Just (start, next))
1020reverse' m =
1021 A.flattenArraysRev
1022 $ fromStreamK
1023 $ K.reverse
1024 $ toStreamK
1025 $ A.fromStreamDArraysOf A.defaultChunkSize m
1028------------------------------------------------------------------------------
1029-- Grouping/Splitting
1030------------------------------------------------------------------------------
1032{-# INLINE_NORMAL splitSuffixBy' #-}
1033splitSuffixBy' :: Monad m
1034 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1035splitSuffixBy' predicate f (Stream step state) =
1036 Stream (stepOuter f) (Just state)
1038 where
1040 {-# INLINE_LATE stepOuter #-}
1041 stepOuter (Fold fstep initial done) gst (Just st) = do
1042 res <- step (adaptState gst) st
1043 case res of
1044 Yield x s -> do
1045 acc <- initial
1046 acc' <- fstep acc x
1047 if (predicate x)
1048 then done acc' >>= \val -> return $ Yield val (Just s)
1049 else go SPEC s acc'
1051 Skip s -> return $ Skip $ Just s
1052 Stop -> return Stop
1054 where
1056 go !_ stt !acc = do
1057 res <- step (adaptState gst) stt
1058 case res of
1059 Yield x s -> do
1060 acc' <- fstep acc x
1061 if (predicate x)
1062 then done acc' >>= \val -> return $ Yield val (Just s)
1063 else go SPEC s acc'
1064 Skip s -> go SPEC s acc
1065 Stop -> done acc >>= \val -> return $ Yield val Nothing
1067 stepOuter _ _ Nothing = return Stop
1069{-# INLINE_NORMAL groupsBy #-}
1070groupsBy :: Monad m
1071 => (a -> a -> Bool)
1072 -> Fold m a b
1073 -> Stream m a
1074 -> Stream m b
1075groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1077 where
1079 {-# INLINE_LATE stepOuter #-}
1080 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1081 res <- step (adaptState gst) st
1082 case res of
1083 Yield x s -> do
1084 acc <- initial
1085 acc' <- fstep acc x
1086 go SPEC x s acc'
1088 Skip s -> return $ Skip $ (Just s, Nothing)
1089 Stop -> return Stop
1091 where
1093 go !_ prev stt !acc = do
1094 res <- step (adaptState gst) stt
1095 case res of
1096 Yield x s -> do
1097 if cmp x prev
1098 then do
1099 acc' <- fstep acc x
1100 go SPEC prev s acc'
1101 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1102 Skip s -> go SPEC prev s acc
1103 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1105 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1106 acc <- initial
1107 acc' <- fstep acc prev
1108 go SPEC st acc'
1110 where
1112 -- XXX code duplicated from the previous equation
1113 go !_ stt !acc = do
1114 res <- step (adaptState gst) stt
1115 case res of
1116 Yield x s -> do
1117 if cmp x prev
1118 then do
1119 acc' <- fstep acc x
1120 go SPEC s acc'
1121 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1122 Skip s -> go SPEC s acc
1123 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1125 stepOuter _ _ (Nothing,_) = return Stop
1127{-# INLINE_NORMAL groupsRollingBy #-}
1128groupsRollingBy :: Monad m
1129 => (a -> a -> Bool)
1130 -> Fold m a b
1131 -> Stream m a
1132 -> Stream m b
1133groupsRollingBy cmp f (Stream step state) =
1134 Stream (stepOuter f) (Just state, Nothing)
1135 where
1137 {-# INLINE_LATE stepOuter #-}
1138 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1139 res <- step (adaptState gst) st
1140 case res of
1141 Yield x s -> do
1142 acc <- initial
1143 acc' <- fstep acc x
1144 go SPEC x s acc'
1146 Skip s -> return $ Skip $ (Just s, Nothing)
1147 Stop -> return Stop
1149 where
1150 go !_ prev stt !acc = do
1151 res <- step (adaptState gst) stt
1152 case res of
1153 Yield x s -> do
1154 if cmp prev x
1155 then do
1156 acc' <- fstep acc x
1157 go SPEC x s acc'
1158 else
1159 done acc >>= \r -> return $ Yield r (Just s, Just x)
1160 Skip s -> go SPEC prev s acc
1161 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1163 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1164 acc <- initial
1165 acc' <- fstep acc prev'
1166 go SPEC prev' st acc'
1168 where
1169 go !_ prevv stt !acc = do
1170 res <- step (adaptState gst) stt
1171 case res of
1172 Yield x s -> do
1173 if cmp prevv x
1174 then do
1175 acc' <- fstep acc x
1176 go SPEC x s acc'
1177 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1178 Skip s -> go SPEC prevv s acc
1179 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1181 stepOuter _ _ (Nothing, _) = return Stop
1183{-# INLINE_NORMAL splitBy #-}
1184splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1185splitBy predicate f (Stream step state) = Stream (step' f) (Just state)
1187 where
1189 {-# INLINE_LATE step' #-}
1190 step' (Fold fstep initial done) gst (Just st) = initial >>= go SPEC st
1192 where
1194 go !_ stt !acc = do
1195 res <- step (adaptState gst) stt
1196 case res of
1197 Yield x s -> do
1198 if predicate x
1199 then done acc >>= \r -> return $ Yield r (Just s)
1200 else do
1201 acc' <- fstep acc x
1202 go SPEC s acc'
1203 Skip s -> go SPEC s acc
1204 Stop -> done acc >>= \r -> return $ Yield r Nothing
1206 step' _ _ Nothing = return Stop
1208-- XXX requires -funfolding-use-threshold=150 in lines-unlines benchmark
1209{-# INLINE_NORMAL splitSuffixBy #-}
1210splitSuffixBy :: Monad m
1211 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1212splitSuffixBy predicate f (Stream step state) = Stream (step' f) (Just state)
1214 where
1216 {-# INLINE_LATE step' #-}
1217 step' (Fold fstep initial done) gst (Just st) = do
1218 res <- step (adaptState gst) st
1219 case res of
1220 Yield x s -> do
1221 acc <- initial
1222 if predicate x
1223 then done acc >>= \val -> return $ Yield val (Just s)
1224 else do
1225 acc' <- fstep acc x
1226 go SPEC s acc'
1228 Skip s -> return $ Skip $ Just s
1229 Stop -> return Stop
1231 where
1233 go !_ stt !acc = do
1234 res <- step (adaptState gst) stt
1235 case res of
1236 Yield x s -> do
1237 if predicate x
1238 then done acc >>= \r -> return $ Yield r (Just s)
1239 else do
1240 acc' <- fstep acc x
1241 go SPEC s acc'
1242 Skip s -> go SPEC s acc
1243 Stop -> done acc >>= \r -> return $ Yield r Nothing
1245 step' _ _ Nothing = return Stop
1247{-# INLINE_NORMAL wordsBy #-}
1248wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1249wordsBy predicate f (Stream step state) = Stream (stepOuter f) (Just state)
1251 where
1253 {-# INLINE_LATE stepOuter #-}
1254 stepOuter (Fold fstep initial done) gst (Just st) = do
1255 res <- step (adaptState gst) st
1256 case res of
1257 Yield x s -> do
1258 if predicate x
1259 then return $ Skip (Just s)
1260 else do
1261 acc <- initial
1262 acc' <- fstep acc x
1263 go SPEC s acc'
1265 Skip s -> return $ Skip $ Just s
1266 Stop -> return Stop
1268 where
1270 go !_ stt !acc = do
1271 res <- step (adaptState gst) stt
1272 case res of
1273 Yield x s -> do
1274 if predicate x
1275 then done acc >>= \r -> return $ Yield r (Just s)
1276 else do
1277 acc' <- fstep acc x
1278 go SPEC s acc'
1279 Skip s -> go SPEC s acc
1280 Stop -> done acc >>= \r -> return $ Yield r Nothing
1282 stepOuter _ _ Nothing = return Stop
1284-- String search algorithms:
1285-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1288-- TODO can we unify the splitting operations using a splitting configuration
1289-- like in the split package.
1291data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1293data SplitOptions = SplitOptions
1294 { style :: SplitStyle
1295 , withSep :: Bool -- ^ keep the separators in output
1296 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1297 -- , trimHead :: Bool -- ^ drop blank at head
1298 -- , trimTail :: Bool -- ^ drop blank at tail
1302data SplitOnState s a =
1303 GO_START
1304 | GO_EMPTY_PAT s
1305 | GO_SINGLE_PAT s a
1306 | GO_SHORT_PAT s
1307 | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
1308 | GO_DONE
1310{-# INLINE_NORMAL splitOn #-}
1311splitOn
1312 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1313 => Array a
1314 -> Fold m a b
1315 -> Stream m a
1316 -> Stream m b
1317splitOn patArr@Array{..} (Fold fstep initial done) (Stream step state) =
1318 Stream stepOuter GO_START
1320 where
1322 patLen = A.length patArr
1323 maxIndex = patLen - 1
1324 elemBits = sizeOf (undefined :: a) * 8
1326 {-# INLINE_LATE stepOuter #-}
1327 stepOuter _ GO_START =
1328 if patLen == 0
1329 then return $ Skip $ GO_EMPTY_PAT state
1330 else if patLen == 1
1331 then do
1332 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1333 return $ Skip $ GO_SINGLE_PAT state r
1334 else if sizeOf (undefined :: a) * patLen
1335 <= sizeOf (undefined :: Word)
1336 then return $ Skip $ GO_SHORT_PAT state
1337 else do
1338 (rb, rhead) <- liftIO $ RB.new patLen
1339 return $ Skip $ GO_KARP_RABIN state rb rhead
1341 stepOuter gst (GO_SINGLE_PAT stt pat) = initial >>= go SPEC stt
1343 where
1345 go !_ st !acc = do
1346 res <- step (adaptState gst) st
1347 case res of
1348 Yield x s -> do
1349 if pat == x
1350 then do
1351 r <- done acc
1352 return $ Yield r (GO_SINGLE_PAT s pat)
1353 else fstep acc x >>= go SPEC s
1354 Skip s -> go SPEC s acc
1355 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1357 stepOuter gst (GO_SHORT_PAT stt) = initial >>= go0 SPEC 0 (0 :: Word) stt
1359 where
1361 mask :: Word
1362 mask = (1 `shiftL` (elemBits * patLen)) - 1
1364 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1366 patWord :: Word
1367 patWord = mask .&. A.foldl' addToWord 0 patArr
1369 go0 !_ !idx wrd st !acc = do
1370 res <- step (adaptState gst) st
1371 case res of
1372 Yield x s -> do
1373 let wrd' = addToWord wrd x
1374 if idx == maxIndex
1375 then do
1376 if wrd' .&. mask == patWord
1377 then do
1378 r <- done acc
1379 return $ Yield r (GO_SHORT_PAT s)
1380 else go1 SPEC wrd' s acc
1381 else go0 SPEC (idx + 1) wrd' s acc
1382 Skip s -> go0 SPEC idx wrd s acc
1383 Stop -> do
1384 acc' <- if idx /= 0
1385 then go2 wrd idx acc
1386 else return acc
1387 done acc' >>= \r -> return $ Yield r GO_DONE
1389 {-# INLINE go1 #-}
1390 go1 !_ wrd st !acc = do
1391 res <- step (adaptState gst) st
1392 case res of
1393 Yield x s -> do
1394 let wrd' = addToWord wrd x
1395 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1396 acc' <- fstep acc (toEnum $ fromIntegral old)
1397 if wrd' .&. mask == patWord
1398 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1399 else go1 SPEC wrd' s acc'
1400 Skip s -> go1 SPEC wrd s acc
1401 Stop -> do
1402 acc' <- go2 wrd patLen acc
1403 done acc' >>= \r -> return $ Yield r GO_DONE
1405 go2 !wrd !n !acc | n > 0 = do
1406 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1407 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1408 go2 _ _ acc = return acc
1410 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1411 initial >>= go0 SPEC 0 rhead stt
1413 where
1415 k = 2891336453 :: Word32
1416 coeff = k ^ patLen
1417 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1418 deltaCksum cksum old new =
1419 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1421 -- XXX shall we use a random starting hash or 1 instead of 0?
1422 patHash = A.foldl' addCksum 0 patArr
1424 -- rh == ringHead
1425 go0 !_ !idx !rh st !acc = do
1426 res <- step (adaptState gst) st
1427 case res of
1428 Yield x s -> do
1429 rh' <- liftIO $ RB.unsafeInsert rb rh x
1430 if idx == maxIndex
1431 then do
1432 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1433 let !ringHash = fold addCksum 0 rb
1434 if ringHash == patHash
1435 then go2 SPEC ringHash rh' s acc
1436 else go1 SPEC ringHash rh' s acc
1437 else go0 SPEC (idx + 1) rh' s acc
1438 Skip s -> go0 SPEC idx rh s acc
1439 Stop -> do
1440 !acc' <- if idx /= 0
1441 then RB.unsafeFoldRingM rh fstep acc rb
1442 else return acc
1443 done acc' >>= \r -> return $ Yield r GO_DONE
1445 -- XXX Theoretically this code can do 4 times faster if GHC generates
1446 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1447 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1448 -- the generated code changes drastically and becomes 4x slower. Need
1449 -- to investigate what is going on with GHC.
1450 {-# INLINE go1 #-}
1451 go1 !_ !cksum !rh st !acc = do
1452 res <- step (adaptState gst) st
1453 case res of
1454 Yield x s -> do
1455 old <- liftIO $ peek rh
1456 let cksum' = deltaCksum cksum old x
1457 acc' <- fstep acc old
1459 if (cksum' == patHash)
1460 then do
1461 rh' <- liftIO (RB.unsafeInsert rb rh x)
1462 go2 SPEC cksum' rh' s acc'
1463 else do
1464 rh' <- liftIO (RB.unsafeInsert rb rh x)
1465 go1 SPEC cksum' rh' s acc'
1466 Skip s -> go1 SPEC cksum rh s acc
1467 Stop -> do
1468 acc' <- RB.unsafeFoldRingFullM rh fstep acc rb
1469 done acc' >>= \r -> return $ Yield r GO_DONE
1471 go2 !_ !cksum' !rh' s !acc' = do
1472 if RB.unsafeEqArray rb rh' patArr
1473 then do
1474 r <- done acc'
1475 return $ Yield r (GO_KARP_RABIN s rb rhead)
1476 else go1 SPEC cksum' rh' s acc'
1478 stepOuter gst (GO_EMPTY_PAT st) = do
1479 res <- step (adaptState gst) st
1480 case res of
1481 Yield x s -> do
1482 acc <- initial
1483 acc' <- fstep acc x
1484 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1485 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1486 Stop -> return Stop
1488 stepOuter _ GO_DONE = return Stop
1490{-# INLINE_NORMAL splitSuffixOn #-}
1491splitSuffixOn
1492 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1493 => Bool
1494 -> Array a
1495 -> Fold m a b
1496 -> Stream m a
1497 -> Stream m b
1498splitSuffixOn withSep patArr@Array{..} (Fold fstep initial done)
1499 (Stream step state) =
1500 Stream stepOuter GO_START
1502 where
1504 patLen = A.length patArr
1505 maxIndex = patLen - 1
1506 elemBits = sizeOf (undefined :: a) * 8
1508 {-# INLINE_LATE stepOuter #-}
1509 stepOuter _ GO_START =
1510 if patLen == 0
1511 then return $ Skip $ GO_EMPTY_PAT state
1512 else if patLen == 1
1513 then do
1514 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1515 return $ Skip $ GO_SINGLE_PAT state r
1516 else if sizeOf (undefined :: a) * patLen
1517 <= sizeOf (undefined :: Word)
1518 then return $ Skip $ GO_SHORT_PAT state
1519 else do
1520 (rb, rhead) <- liftIO $ RB.new patLen
1521 return $ Skip $ GO_KARP_RABIN state rb rhead
1523 stepOuter gst (GO_SINGLE_PAT stt pat) = do
1524 -- This first part is the only difference between splitOn and
1525 -- splitSuffixOn.
1526 -- If the last element is a separator do not issue a blank segment.
1527 res <- step (adaptState gst) stt
1528 case res of
1529 Yield x s -> do
1530 acc <- initial
1531 if pat == x
1532 then do
1533 acc' <- if withSep then fstep acc x else return acc
1534 done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
1535 else fstep acc x >>= go SPEC s
1536 Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
1537 Stop -> return Stop
1539 where
1541 -- This is identical for splitOn and splitSuffixOn
1542 go !_ st !acc = do
1543 res <- step (adaptState gst) st
1544 case res of
1545 Yield x s -> do
1546 if pat == x
1547 then do
1548 acc' <- if withSep then fstep acc x else return acc
1549 r <- done acc'
1550 return $ Yield r (GO_SINGLE_PAT s pat)
1551 else fstep acc x >>= go SPEC s
1552 Skip s -> go SPEC s acc
1553 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1555 stepOuter gst (GO_SHORT_PAT stt) = do
1557 -- Call "initial" only if the stream yields an element, otherwise we
1558 -- may call "initial" but never yield anything. initial may produce a
1559 -- side effect, therefore we will end up doing and discard a side
1560 -- effect.
1562 let idx = 0
1563 let wrd = 0
1564 res <- step (adaptState gst) stt
1565 case res of
1566 Yield x s -> do
1567 acc <- initial
1568 let wrd' = addToWord wrd x
1569 acc' <- if withSep then fstep acc x else return acc
1570 if idx == maxIndex
1571 then do
1572 if wrd' .&. mask == patWord
1573 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1574 else go0 SPEC (idx + 1) wrd' s acc'
1575 else go0 SPEC (idx + 1) wrd' s acc'
1576 Skip s -> return $ Skip (GO_SHORT_PAT s)
1577 Stop -> return Stop
1579 where
1581 mask :: Word
1582 mask = (1 `shiftL` (elemBits * patLen)) - 1
1584 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1586 patWord :: Word
1587 patWord = mask .&. A.foldl' addToWord 0 patArr
1589 go0 !_ !idx wrd st !acc = do
1590 res <- step (adaptState gst) st
1591 case res of
1592 Yield x s -> do
1593 let wrd' = addToWord wrd x
1594 acc' <- if withSep then fstep acc x else return acc
1595 if idx == maxIndex
1596 then do
1597 if wrd' .&. mask == patWord
1598 then do
1599 r <- done acc'
1600 return $ Yield r (GO_SHORT_PAT s)
1601 else go1 SPEC wrd' s acc'
1602 else go0 SPEC (idx + 1) wrd' s acc'
1603 Skip s -> go0 SPEC idx wrd s acc
1604 Stop -> do
1605 if (idx == maxIndex) && (wrd .&. mask == patWord)
1606 then return Stop
1607 else do
1608 acc' <- if idx /= 0 && not withSep
1609 then go2 wrd idx acc
1610 else return acc
1611 done acc' >>= \r -> return $ Yield r GO_DONE
1613 {-# INLINE go1 #-}
1614 go1 !_ wrd st !acc = do
1615 res <- step (adaptState gst) st
1616 case res of
1617 Yield x s -> do
1618 let wrd' = addToWord wrd x
1619 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1620 acc' <- if withSep
1621 then fstep acc x
1622 else fstep acc (toEnum $ fromIntegral old)
1623 if wrd' .&. mask == patWord
1624 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1625 else go1 SPEC wrd' s acc'
1626 Skip s -> go1 SPEC wrd s acc
1627 Stop ->
1628 -- If the last sequence is a separator do not issue a blank
1629 -- segment.
1630 if wrd .&. mask == patWord
1631 then return Stop
1632 else do
1633 acc' <- if withSep
1634 then return acc
1635 else go2 wrd patLen acc
1636 done acc' >>= \r -> return $ Yield r GO_DONE
1638 go2 !wrd !n !acc | n > 0 = do
1639 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1640 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1641 go2 _ _ acc = return acc
1643 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1644 let idx = 0
1645 res <- step (adaptState gst) stt
1646 case res of
1647 Yield x s -> do
1648 acc <- initial
1649 acc' <- if withSep then fstep acc x else return acc
1650 rh' <- liftIO (RB.unsafeInsert rb rhead x)
1651 if idx == maxIndex
1652 then do
1653 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1654 let !ringHash = fold addCksum 0 rb
1655 if ringHash == patHash
1656 then go2 SPEC ringHash rh' s acc'
1657 else go0 SPEC (idx + 1) rh' s acc'
1658 else go0 SPEC (idx + 1) rh' s acc'
1659 Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
1660 Stop -> return Stop
1662 where
1664 k = 2891336453 :: Word32
1665 coeff = k ^ patLen
1666 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1667 deltaCksum cksum old new =
1668 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1670 -- XXX shall we use a random starting hash or 1 instead of 0?
1671 patHash = A.foldl' addCksum 0 patArr
1673 -- rh == ringHead
1674 go0 !_ !idx !rh st !acc = do
1675 res <- step (adaptState gst) st
1676 case res of
1677 Yield x s -> do
1678 acc' <- if withSep then fstep acc x else return acc
1679 rh' <- liftIO (RB.unsafeInsert rb rh x)
1680 if idx == maxIndex
1681 then do
1682 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1683 let !ringHash = fold addCksum 0 rb
1684 if ringHash == patHash
1685 then go2 SPEC ringHash rh' s acc'
1686 else go1 SPEC ringHash rh' s acc'
1687 else go0 SPEC (idx + 1) rh' s acc'
1688 Skip s -> go0 SPEC idx rh s acc
1689 Stop -> do
1690 -- do not issue a blank segment when we end at pattern
1691 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
1692 then return Stop
1693 else do
1694 !acc' <- if idx /= 0 && not withSep
1695 then RB.unsafeFoldRingM rh fstep acc rb
1696 else return acc
1697 done acc' >>= \r -> return $ Yield r GO_DONE
1699 -- XXX Theoretically this code can do 4 times faster if GHC generates
1700 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1701 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1702 -- the generated code changes drastically and becomes 4x slower. Need
1703 -- to investigate what is going on with GHC.
1704 {-# INLINE go1 #-}
1705 go1 !_ !cksum !rh st !acc = do
1706 res <- step (adaptState gst) st
1707 case res of
1708 Yield x s -> do
1709 old <- liftIO $ peek rh
1710 let cksum' = deltaCksum cksum old x
1711 acc' <- if withSep
1712 then fstep acc x
1713 else fstep acc old
1715 if (cksum' == patHash)
1716 then do
1717 rh' <- liftIO (RB.unsafeInsert rb rh x)
1718 go2 SPEC cksum' rh' s acc'
1719 else do
1720 rh' <- liftIO (RB.unsafeInsert rb rh x)
1721 go1 SPEC cksum' rh' s acc'
1722 Skip s -> go1 SPEC cksum rh s acc
1723 Stop -> do
1724 if RB.unsafeEqArray rb rh patArr
1725 then return Stop
1726 else do
1727 acc' <- if withSep
1728 then return acc
1729 else RB.unsafeFoldRingFullM rh fstep acc rb
1730 done acc' >>= \r -> return $ Yield r GO_DONE
1732 go2 !_ !cksum' !rh' s !acc' = do
1733 if RB.unsafeEqArray rb rh' patArr
1734 then do
1735 r <- done acc'
1736 return $ Yield r (GO_KARP_RABIN s rb rhead)
1737 else go1 SPEC cksum' rh' s acc'
1739 stepOuter gst (GO_EMPTY_PAT st) = do
1740 res <- step (adaptState gst) st
1741 case res of
1742 Yield x s -> do
1743 acc <- initial
1744 acc' <- fstep acc x
1745 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1746 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1747 Stop -> return Stop
1749 stepOuter _ GO_DONE = return Stop
1751data SplitState s arr
1752 = SplitInitial s
1753 | SplitBuffering s arr
1754 | SplitSplitting s arr
1755 | SplitYielding arr (SplitState s arr)
1756 | SplitFinishing
1758-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
1759-- split using a splitBy like combinator. The Fold would consume upto the
1760-- separator and return any leftover which can then be fed to the next fold.
1762-- We can revisit this once we have partial folds/parsers.
1764-- | Performs infix separator style splitting.
1765{-# INLINE_NORMAL splitInnerBy #-}
1766splitInnerBy
1767 :: Monad m
1768 => (f a -> m (f a, Maybe (f a))) -- splitter
1769 -> (f a -> f a -> m (f a)) -- joiner
1770 -> Stream m (f a)
1771 -> Stream m (f a)
1772splitInnerBy splitter joiner (Stream step1 state1) =
1773 (Stream step (SplitInitial state1))
1775 where
1777 {-# INLINE_LATE step #-}
1778 step gst (SplitInitial st) = do
1779 r <- step1 gst st
1780 case r of
1781 Yield x s -> do
1782 (x1, mx2) <- splitter x
1783 return $ case mx2 of
1784 Nothing -> Skip (SplitBuffering s x1)
1785 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
1786 Skip s -> return $ Skip (SplitInitial s)
1787 Stop -> return $ Stop
1789 step gst (SplitBuffering st buf) = do
1790 r <- step1 gst st
1791 case r of
1792 Yield x s -> do
1793 (x1, mx2) <- splitter x
1794 buf' <- joiner buf x1
1795 return $ case mx2 of
1796 Nothing -> Skip (SplitBuffering s buf')
1797 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
1798 Skip s -> return $ Skip (SplitBuffering s buf)
1799 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
1801 step _ (SplitSplitting st buf) = do
1802 (x1, mx2) <- splitter buf
1803 return $ case mx2 of
1804 Nothing -> Skip $ SplitBuffering st x1
1805 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
1807 step _ (SplitYielding x next) = return $ Yield x next
1808 step _ SplitFinishing = return $ Stop
1810-- | Performs infix separator style splitting.
1811{-# INLINE_NORMAL splitInnerBySuffix #-}
1812splitInnerBySuffix
1813 :: (Monad m, Eq (f a), Monoid (f a))
1814 => (f a -> m (f a, Maybe (f a))) -- splitter
1815 -> (f a -> f a -> m (f a)) -- joiner
1816 -> Stream m (f a)
1817 -> Stream m (f a)
1818splitInnerBySuffix splitter joiner (Stream step1 state1) =
1819 (Stream step (SplitInitial state1))
1821 where
1823 {-# INLINE_LATE step #-}
1824 step gst (SplitInitial st) = do
1825 r <- step1 gst st
1826 case r of
1827 Yield x s -> do
1828 (x1, mx2) <- splitter x
1829 return $ case mx2 of
1830 Nothing -> Skip (SplitBuffering s x1)
1831 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
1832 Skip s -> return $ Skip (SplitInitial s)
1833 Stop -> return $ Stop
1835 step gst (SplitBuffering st buf) = do
1836 r <- step1 gst st
1837 case r of
1838 Yield x s -> do
1839 (x1, mx2) <- splitter x
1840 buf' <- joiner buf x1
1841 return $ case mx2 of
1842 Nothing -> Skip (SplitBuffering s buf')
1843 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
1844 Skip s -> return $ Skip (SplitBuffering s buf)
1845 Stop -> return $
1846 if buf == mempty
1847 then Stop
1848 else Skip (SplitYielding buf SplitFinishing)
1850 step _ (SplitSplitting st buf) = do
1851 (x1, mx2) <- splitter buf
1852 return $ case mx2 of
1853 Nothing -> Skip $ SplitBuffering st x1
1854 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
1856 step _ (SplitYielding x next) = return $ Yield x next
1857 step _ SplitFinishing = return $ Stop
1859------------------------------------------------------------------------------
1860-- Substreams
1861------------------------------------------------------------------------------
1863{-# INLINE_NORMAL isPrefixOf #-}
1864isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1865isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1866 where
1867 go (sa, sb, Nothing) = do
1868 r <- stepa defState sa
1869 case r of
1870 Yield x sa' -> go (sa', sb, Just x)
1871 Skip sa' -> go (sa', sb, Nothing)
1872 Stop -> return True
1874 go (sa, sb, Just x) = do
1875 r <- stepb defState sb
1876 case r of
1877 Yield y sb' ->
1878 if x == y
1879 then go (sa, sb', Nothing)
1880 else return False
1881 Skip sb' -> go (sa, sb', Just x)
1882 Stop -> return False
1884{-# INLINE_NORMAL isSubsequenceOf #-}
1885isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1886isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1887 where
1888 go (sa, sb, Nothing) = do
1889 r <- stepa defState sa
1890 case r of
1891 Yield x sa' -> go (sa', sb, Just x)
1892 Skip sa' -> go (sa', sb, Nothing)
1893 Stop -> return True
1895 go (sa, sb, Just x) = do
1896 r <- stepb defState sb
1897 case r of
1898 Yield y sb' ->
1899 if x == y
1900 then go (sa, sb', Nothing)
1901 else go (sa, sb', Just x)
1902 Skip sb' -> go (sa, sb', Just x)
1903 Stop -> return False
1905{-# INLINE_NORMAL stripPrefix #-}
1906stripPrefix
1907 :: (Eq a, Monad m)
1908 => Stream m a -> Stream m a -> m (Maybe (Stream m a))
1909stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1910 where
1911 go (sa, sb, Nothing) = do
1912 r <- stepa defState sa
1913 case r of
1914 Yield x sa' -> go (sa', sb, Just x)
1915 Skip sa' -> go (sa', sb, Nothing)
1916 Stop -> return $ Just (Stream stepb sb)
1918 go (sa, sb, Just x) = do
1919 r <- stepb defState sb
1920 case r of
1921 Yield y sb' ->
1922 if x == y
1923 then go (sa, sb', Nothing)
1924 else return Nothing
1925 Skip sb' -> go (sa, sb', Just x)
1926 Stop -> return Nothing
1928------------------------------------------------------------------------------
1929-- Map and Fold
1930------------------------------------------------------------------------------
1932-- | Execute a monadic action for each element of the 'Stream'
1933{-# INLINE_NORMAL mapM_ #-}
1934mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
1935mapM_ m = drain . mapM m
1937-------------------------------------------------------------------------------
1938-- Stream transformations using Unfolds
1939-------------------------------------------------------------------------------
1941-- Define a unique structure to use in inspection testing
1942data ConcatMapUState o i =
1943 ConcatMapUOuter o
1944 | ConcatMapUInner o i
1946-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
1947-- to streams and then flattens the generated streams into a single output
1948-- stream.
1950-- This is like 'concatMap' but uses an unfold with an explicit state to
1951-- generate the stream instead of a 'Stream' type generator. This allows better
1952-- optimization via fusion. This can be many times more efficient than
1953-- 'concatMap'.
1955{-# INLINE_NORMAL concatMapU #-}
1956concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
1957concatMapU (Unfold istep inject) (Stream ostep ost) =
1958 Stream step (ConcatMapUOuter ost)
1959 where
1960 {-# INLINE_LATE step #-}
1961 step gst (ConcatMapUOuter o) = do
1962 r <- ostep (adaptState gst) o
1963 case r of
1964 Yield a o' -> do
1965 i <- inject a
1966 i `seq` return (Skip (ConcatMapUInner o' i))
1967 Skip o' -> return $ Skip (ConcatMapUOuter o')
1968 Stop -> return $ Stop
1970 step _ (ConcatMapUInner o i) = do
1971 r <- istep i
1972 return $ case r of
1973 Yield x i' -> Yield x (ConcatMapUInner o i')
1974 Skip i' -> Skip (ConcatMapUInner o i')
1975 Stop -> Skip (ConcatMapUOuter o)
1977data ConcatUnfoldInterleaveState o i =
1978 ConcatUnfoldInterleaveOuter o [i]
1979 | ConcatUnfoldInterleaveInner o [i]
1980 | ConcatUnfoldInterleaveInnerL [i] [i]
1981 | ConcatUnfoldInterleaveInnerR [i] [i]
1983-- XXX use arrays to store state instead of lists.
1984-- XXX In general we can use different scheduling strategies e.g. how to
1985-- schedule the outer vs inner loop or assigning weights to different streams
1986-- or outer and inner loops.
1988-- After a yield, switch to the next stream. Do not switch streams on Skip.
1989-- Yield from outer stream switches to the inner stream.
1991-- There are two choices here, (1) exhaust the outer stream first and then
1992-- start yielding from the inner streams, this is much simpler to implement,
1993-- (2) yield at least one element from an inner stream before going back to
1994-- outer stream and opening the next stream from it.
1996-- Ideally, we need some scheduling bias to inner streams vs outer stream.
1997-- Maybe we can configure the behavior.
1999{-# INLINE_NORMAL concatUnfoldInterleave #-}
2000concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2001concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
2002 Stream step (ConcatUnfoldInterleaveOuter ost [])
2003 where
2004 {-# INLINE_LATE step #-}
2005 step gst (ConcatUnfoldInterleaveOuter o ls) = do
2006 r <- ostep (adaptState gst) o
2007 case r of
2008 Yield a o' -> do
2009 i <- inject a
2010 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2011 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
2012 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2014 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
2015 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2016 r <- istep st
2017 return $ case r of
2018 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2019 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
2020 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2022 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2023 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2024 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2026 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2027 r <- istep st
2028 return $ case r of
2029 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2030 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
2031 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2033 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2034 step _ (ConcatUnfoldInterleaveInnerR ls []) =
2035 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2037 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2038 r <- istep st
2039 return $ case r of
2040 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2041 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
2042 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2044-- XXX In general we can use different scheduling strategies e.g. how to
2045-- schedule the outer vs inner loop or assigning weights to different streams
2046-- or outer and inner loops.
2048-- This could be inefficient if the tasks are too small.
2050-- Compared to concatUnfoldInterleave this one switches streams on Skips.
2052{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
2053concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2054concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
2055 Stream step (ConcatUnfoldInterleaveOuter ost [])
2056 where
2057 {-# INLINE_LATE step #-}
2058 step gst (ConcatUnfoldInterleaveOuter o ls) = do
2059 r <- ostep (adaptState gst) o
2060 case r of
2061 Yield a o' -> do
2062 i <- inject a
2063 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2064 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
2065 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2067 step _ (ConcatUnfoldInterleaveInner o []) =
2068 return $ Skip (ConcatUnfoldInterleaveOuter o [])
2070 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2071 r <- istep st
2072 return $ case r of
2073 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2074 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
2075 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2077 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2078 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2079 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2081 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2082 r <- istep st
2083 return $ case r of
2084 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2085 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
2086 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2088 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2089 step _ (ConcatUnfoldInterleaveInnerR ls []) =
2090 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2092 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2093 r <- istep st
2094 return $ case r of
2095 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2096 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2097 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2099data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
2101-- Note that this could be much faster compared to the CPS stream. However, as
2102-- the number of streams being composed increases this may become expensive.
2103-- Need to see where the breaking point is between the two.
2105{-# INLINE_NORMAL append #-}
2106append :: Monad m => Stream m a -> Stream m a -> Stream m a
2107append (Stream step1 state1) (Stream step2 state2) =
2108 Stream step (AppendFirst state1)
2110 where
2112 {-# INLINE_LATE step #-}
2113 step gst (AppendFirst st) = do
2114 r <- step1 gst st
2115 return $ case r of
2116 Yield a s -> Yield a (AppendFirst s)
2117 Skip s -> Skip (AppendFirst s)
2118 Stop -> Skip (AppendSecond state2)
2120 step gst (AppendSecond st) = do
2121 r <- step2 gst st
2122 return $ case r of
2123 Yield a s -> Yield a (AppendSecond s)
2124 Skip s -> Skip (AppendSecond s)
2125 Stop -> Stop
2127data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
2128 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
2130{-# INLINE_NORMAL interleave #-}
2131interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
2132interleave (Stream step1 state1) (Stream step2 state2) =
2133 Stream step (InterleaveFirst state1 state2)
2135 where
2137 {-# INLINE_LATE step #-}
2138 step gst (InterleaveFirst st1 st2) = do
2139 r <- step1 gst st1
2140 return $ case r of
2141 Yield a s -> Yield a (InterleaveSecond s st2)
2142 Skip s -> Skip (InterleaveFirst s st2)
2143 Stop -> Skip (InterleaveSecondOnly st2)
2145 step gst (InterleaveSecond st1 st2) = do
2146 r <- step2 gst st2
2147 return $ case r of
2148 Yield a s -> Yield a (InterleaveFirst st1 s)
2149 Skip s -> Skip (InterleaveSecond st1 s)
2150 Stop -> Skip (InterleaveFirstOnly st1)
2152 step gst (InterleaveFirstOnly st1) = do
2153 r <- step1 gst st1
2154 return $ case r of
2155 Yield a s -> Yield a (InterleaveFirstOnly s)
2156 Skip s -> Skip (InterleaveFirstOnly s)
2157 Stop -> Stop
2159 step gst (InterleaveSecondOnly st2) = do
2160 r <- step2 gst st2
2161 return $ case r of
2162 Yield a s -> Yield a (InterleaveSecondOnly s)
2163 Skip s -> Skip (InterleaveSecondOnly s)
2164 Stop -> Stop
2166{-# INLINE_NORMAL interleaveMin #-}
2167interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
2168interleaveMin (Stream step1 state1) (Stream step2 state2) =
2169 Stream step (InterleaveFirst state1 state2)
2171 where
2173 {-# INLINE_LATE step #-}
2174 step gst (InterleaveFirst st1 st2) = do
2175 r <- step1 gst st1
2176 return $ case r of
2177 Yield a s -> Yield a (InterleaveSecond s st2)
2178 Skip s -> Skip (InterleaveFirst s st2)
2179 Stop -> Stop
2181 step gst (InterleaveSecond st1 st2) = do
2182 r <- step2 gst st2
2183 return $ case r of
2184 Yield a s -> Yield a (InterleaveFirst st1 s)
2185 Skip s -> Skip (InterleaveSecond st1 s)
2186 Stop -> Stop
2188 step _ (InterleaveFirstOnly _) = undefined
2189 step _ (InterleaveSecondOnly _) = undefined
2191{-# INLINE_NORMAL interleaveSuffix #-}
2192interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
2193interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
2194 Stream step (InterleaveFirst state1 state2)
2196 where
2198 {-# INLINE_LATE step #-}
2199 step gst (InterleaveFirst st1 st2) = do
2200 r <- step1 gst st1
2201 return $ case r of
2202 Yield a s -> Yield a (InterleaveSecond s st2)
2203 Skip s -> Skip (InterleaveFirst s st2)
2204 Stop -> Stop
2206 step gst (InterleaveSecond st1 st2) = do
2207 r <- step2 gst st2
2208 return $ case r of
2209 Yield a s -> Yield a (InterleaveFirst st1 s)
2210 Skip s -> Skip (InterleaveSecond st1 s)
2211 Stop -> Skip (InterleaveFirstOnly st1)
2213 step gst (InterleaveFirstOnly st1) = do
2214 r <- step1 gst st1
2215 return $ case r of
2216 Yield a s -> Yield a (InterleaveFirstOnly s)
2217 Skip s -> Skip (InterleaveFirstOnly s)
2218 Stop -> Stop
2220 step _ (InterleaveSecondOnly _) = undefined
2222data InterleaveInfixState s1 s2 a
2223 = InterleaveInfixFirst s1 s2
2224 | InterleaveInfixSecondBuf s1 s2
2225 | InterleaveInfixSecondYield s1 s2 a
2226 | InterleaveInfixFirstYield s1 s2 a
2227 | InterleaveInfixFirstOnly s1
2229{-# INLINE_NORMAL interleaveInfix #-}
2230interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
2231interleaveInfix (Stream step1 state1) (Stream step2 state2) =
2232 Stream step (InterleaveInfixFirst state1 state2)
2234 where
2236 {-# INLINE_LATE step #-}
2237 step gst (InterleaveInfixFirst st1 st2) = do
2238 r <- step1 gst st1
2239 return $ case r of
2240 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
2241 Skip s -> Skip (InterleaveInfixFirst s st2)
2242 Stop -> Stop
2244 step gst (InterleaveInfixSecondBuf st1 st2) = do
2245 r <- step2 gst st2
2246 return $ case r of
2247 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
2248 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
2249 Stop -> Skip (InterleaveInfixFirstOnly st1)
2251 step gst (InterleaveInfixSecondYield st1 st2 x) = do
2252 r <- step1 gst st1
2253 return $ case r of
2254 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
2255 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
2256 Stop -> Stop
2258 step _ (InterleaveInfixFirstYield st1 st2 x) = do
2259 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
2261 step gst (InterleaveInfixFirstOnly st1) = do
2262 r <- step1 gst st1
2263 return $ case r of
2264 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
2265 Skip s -> Skip (InterleaveInfixFirstOnly s)
2266 Stop -> Stop
2268{-# INLINE_NORMAL roundRobin #-}
2269roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
2270roundRobin (Stream step1 state1) (Stream step2 state2) =
2271 Stream step (InterleaveFirst state1 state2)
2273 where
2275 {-# INLINE_LATE step #-}
2276 step gst (InterleaveFirst st1 st2) = do
2277 r <- step1 gst st1
2278 return $ case r of
2279 Yield a s -> Yield a (InterleaveSecond s st2)
2280 Skip s -> Skip (InterleaveSecond s st2)
2281 Stop -> Skip (InterleaveSecondOnly st2)
2283 step gst (InterleaveSecond st1 st2) = do
2284 r <- step2 gst st2
2285 return $ case r of
2286 Yield a s -> Yield a (InterleaveFirst st1 s)
2287 Skip s -> Skip (InterleaveFirst st1 s)
2288 Stop -> Skip (InterleaveFirstOnly st1)
2290 step gst (InterleaveSecondOnly st2) = do
2291 r <- step2 gst st2
2292 return $ case r of
2293 Yield a s -> Yield a (InterleaveSecondOnly s)
2294 Skip s -> Skip (InterleaveSecondOnly s)
2295 Stop -> Stop
2297 step gst (InterleaveFirstOnly st1) = do
2298 r <- step1 gst st1
2299 return $ case r of
2300 Yield a s -> Yield a (InterleaveFirstOnly s)
2301 Skip s -> Skip (InterleaveFirstOnly s)
2302 Stop -> Stop
2304data ICUState s1 s2 i1 i2 =
2305 ICUFirst s1 s2
2306 | ICUSecond s1 s2
2307 | ICUSecondOnly s2
2308 | ICUFirstOnly s1
2309 | ICUFirstInner s1 s2 i1
2310 | ICUSecondInner s1 s2 i2
2311 | ICUFirstOnlyInner s1 i1
2312 | ICUSecondOnlyInner s2 i2
2314-- | Interleave streams (full streams, not the elements) unfolded from two
2315-- input streams and concat. Stop when the first stream stops. If the second
2316-- stream ends before the first one then first stream still keeps running alone
2317-- without any interleaving with the second stream.
2319-- [a1, a2, ... an] [b1, b2 ...]
2320-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2321-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2322-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2324{-# INLINE_NORMAL gintercalateSuffix #-}
2325gintercalateSuffix
2326 :: Monad m
2327 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2328gintercalateSuffix
2329 (Unfold istep1 inject1) (Stream step1 state1)
2330 (Unfold istep2 inject2) (Stream step2 state2) =
2331 Stream step (ICUFirst state1 state2)
2333 where
2335 {-# INLINE_LATE step #-}
2336 step gst (ICUFirst s1 s2) = do
2337 r <- step1 (adaptState gst) s1
2338 case r of
2339 Yield a s -> do
2340 i <- inject1 a
2341 i `seq` return (Skip (ICUFirstInner s s2 i))
2342 Skip s -> return $ Skip (ICUFirst s s2)
2343 Stop -> return Stop
2345 step gst (ICUFirstOnly s1) = do
2346 r <- step1 (adaptState gst) s1
2347 case r of
2348 Yield a s -> do
2349 i <- inject1 a
2350 i `seq` return (Skip (ICUFirstOnlyInner s i))
2351 Skip s -> return $ Skip (ICUFirstOnly s)
2352 Stop -> return Stop
2354 step _ (ICUFirstInner s1 s2 i1) = do
2355 r <- istep1 i1
2356 return $ case r of
2357 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
2358 Skip i' -> Skip (ICUFirstInner s1 s2 i')
2359 Stop -> Skip (ICUSecond s1 s2)
2361 step _ (ICUFirstOnlyInner s1 i1) = do
2362 r <- istep1 i1
2363 return $ case r of
2364 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
2365 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
2366 Stop -> Skip (ICUFirstOnly s1)
2368 step gst (ICUSecond s1 s2) = do
2369 r <- step2 (adaptState gst) s2
2370 case r of
2371 Yield a s -> do
2372 i <- inject2 a
2373 i `seq` return (Skip (ICUSecondInner s1 s i))
2374 Skip s -> return $ Skip (ICUSecond s1 s)
2375 Stop -> return $ Skip (ICUFirstOnly s1)
2377 step _ (ICUSecondInner s1 s2 i2) = do
2378 r <- istep2 i2
2379 return $ case r of
2380 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
2381 Skip i' -> Skip (ICUSecondInner s1 s2 i')
2382 Stop -> Skip (ICUFirst s1 s2)
2384 step _ (ICUSecondOnly _s2) = undefined
2385 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
2387data InterposeSuffixState s1 i1 =
2388 InterposeSuffixFirst s1
2389 -- | InterposeSuffixFirstYield s1 i1
2390 | InterposeSuffixFirstInner s1 i1
2391 | InterposeSuffixSecond s1
2393-- Note that if an unfolded layer turns out to be nil we still emit the
2394-- separator effect. An alternate behavior could be to emit the separator
2395-- effect only if at least one element has been yielded by the unfolding.
2396-- However, that becomes a bit complicated, so we have chosen the former
2397-- behvaior for now.
2398{-# INLINE_NORMAL interposeSuffix #-}
2399interposeSuffix
2400 :: Monad m
2401 => m c -> Unfold m b c -> Stream m b -> Stream m c
2402interposeSuffix
2403 action
2404 (Unfold istep1 inject1) (Stream step1 state1) =
2405 Stream step (InterposeSuffixFirst state1)
2407 where
2409 {-# INLINE_LATE step #-}
2410 step gst (InterposeSuffixFirst s1) = do
2411 r <- step1 (adaptState gst) s1
2412 case r of
2413 Yield a s -> do
2414 i <- inject1 a
2415 i `seq` return (Skip (InterposeSuffixFirstInner s i))
2416 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
2417 Skip s -> return $ Skip (InterposeSuffixFirst s)
2418 Stop -> return Stop
2420 {-
2421 step _ (InterposeSuffixFirstYield s1 i1) = do
2422 r <- istep1 i1
2423 return $ case r of
2424 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
2425 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
2426 Stop -> Skip (InterposeSuffixFirst s1)
2427 -}
2429 step _ (InterposeSuffixFirstInner s1 i1) = do
2430 r <- istep1 i1
2431 return $ case r of
2432 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
2433 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
2434 Stop -> Skip (InterposeSuffixSecond s1)
2436 step _ (InterposeSuffixSecond s1) = do
2437 r <- action
2438 return $ Yield r (InterposeSuffixFirst s1)
2440data ICALState s1 s2 i1 i2 a =
2441 ICALFirst s1 s2
2442 -- | ICALFirstYield s1 s2 i1
2443 | ICALFirstInner s1 s2 i1
2444 | ICALFirstOnly s1
2445 | ICALFirstOnlyInner s1 i1
2446 | ICALSecondInject s1 s2
2447 | ICALFirstInject s1 s2 i2
2448 -- | ICALFirstBuf s1 s2 i1 i2
2449 | ICALSecondInner s1 s2 i1 i2
2450 -- -- | ICALSecondInner s1 s2 i1 i2 a
2451 -- -- | ICALFirstResume s1 s2 i1 i2 a
2453-- | Interleave streams (full streams, not the elements) unfolded from two
2454-- input streams and concat. Stop when the first stream stops. If the second
2455-- stream ends before the first one then first stream still keeps running alone
2456-- without any interleaving with the second stream.
2458-- [a1, a2, ... an] [b1, b2 ...]
2459-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2460-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2461-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2463{-# INLINE_NORMAL gintercalate #-}
2464gintercalate
2465 :: Monad m
2466 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2467gintercalate
2468 (Unfold istep1 inject1) (Stream step1 state1)
2469 (Unfold istep2 inject2) (Stream step2 state2) =
2470 Stream step (ICALFirst state1 state2)
2472 where
2474 {-# INLINE_LATE step #-}
2475 step gst (ICALFirst s1 s2) = do
2476 r <- step1 (adaptState gst) s1
2477 case r of
2478 Yield a s -> do
2479 i <- inject1 a
2480 i `seq` return (Skip (ICALFirstInner s s2 i))
2481 -- i `seq` return (Skip (ICALFirstYield s s2 i))
2482 Skip s -> return $ Skip (ICALFirst s s2)
2483 Stop -> return Stop
2485 {-
2486 step _ (ICALFirstYield s1 s2 i1) = do
2487 r <- istep1 i1
2488 return $ case r of
2489 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
2490 Skip i' -> Skip (ICALFirstYield s1 s2 i')
2491 Stop -> Skip (ICALFirst s1 s2)
2492 -}
2494 step _ (ICALFirstInner s1 s2 i1) = do
2495 r <- istep1 i1
2496 return $ case r of
2497 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
2498 Skip i' -> Skip (ICALFirstInner s1 s2 i')
2499 Stop -> Skip (ICALSecondInject s1 s2)
2501 step gst (ICALFirstOnly s1) = do
2502 r <- step1 (adaptState gst) s1
2503 case r of
2504 Yield a s -> do
2505 i <- inject1 a
2506 i `seq` return (Skip (ICALFirstOnlyInner s i))
2507 Skip s -> return $ Skip (ICALFirstOnly s)
2508 Stop -> return Stop
2510 step _ (ICALFirstOnlyInner s1 i1) = do
2511 r <- istep1 i1
2512 return $ case r of
2513 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
2514 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
2515 Stop -> Skip (ICALFirstOnly s1)
2517 -- We inject the second stream even before checking if the first stream
2518 -- would yield any more elements. There is no clear choice whether we
2519 -- should do this before or after that. Doing it after may make the state
2520 -- machine a bit simpler though.
2521 step gst (ICALSecondInject s1 s2) = do
2522 r <- step2 (adaptState gst) s2
2523 case r of
2524 Yield a s -> do
2525 i <- inject2 a
2526 i `seq` return (Skip (ICALFirstInject s1 s i))
2527 Skip s -> return $ Skip (ICALSecondInject s1 s)
2528 Stop -> return $ Skip (ICALFirstOnly s1)
2530 step gst (ICALFirstInject s1 s2 i2) = do
2531 r <- step1 (adaptState gst) s1
2532 case r of
2533 Yield a s -> do
2534 i <- inject1 a
2535 i `seq` return (Skip (ICALSecondInner s s2 i i2))
2536 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
2537 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
2538 Stop -> return Stop
2540 {-
2541 step _ (ICALFirstBuf s1 s2 i1 i2) = do
2542 r <- istep1 i1
2543 return $ case r of
2544 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
2545 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
2546 Stop -> Stop
2548 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
2549 r <- istep2 i2
2550 return $ case r of
2551 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
2552 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
2553 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
2554 -}
2556 step _ (ICALSecondInner s1 s2 i1 i2) = do
2557 r <- istep2 i2
2558 return $ case r of
2559 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
2560 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
2561 Stop -> Skip (ICALFirstInner s1 s2 i1)
2562 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
2564 {-
2565 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
2566 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
2567 -}
2569data InterposeState s1 i1 a =
2570 InterposeFirst s1
2571 -- | InterposeFirstYield s1 i1
2572 | InterposeFirstInner s1 i1
2573 | InterposeFirstInject s1
2574 -- | InterposeFirstBuf s1 i1
2575 | InterposeSecondYield s1 i1
2576 -- -- | InterposeSecondYield s1 i1 a
2577 -- -- | InterposeFirstResume s1 i1 a
2579-- Note that this only interposes the pure values, we may run many effects to
2580-- generate those values as some effects may not generate anything (Skip).
2581{-# INLINE_NORMAL interpose #-}
2582interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
2583interpose
2584 action
2585 (Unfold istep1 inject1) (Stream step1 state1) =
2586 Stream step (InterposeFirst state1)
2588 where
2590 {-# INLINE_LATE step #-}
2591 step gst (InterposeFirst s1) = do
2592 r <- step1 (adaptState gst) s1
2593 case r of
2594 Yield a s -> do
2595 i <- inject1 a
2596 i `seq` return (Skip (InterposeFirstInner s i))
2597 -- i `seq` return (Skip (InterposeFirstYield s i))
2598 Skip s -> return $ Skip (InterposeFirst s)
2599 Stop -> return Stop
2601 {-
2602 step _ (InterposeFirstYield s1 i1) = do
2603 r <- istep1 i1
2604 return $ case r of
2605 Yield x i' -> Yield x (InterposeFirstInner s1 i')
2606 Skip i' -> Skip (InterposeFirstYield s1 i')
2607 Stop -> Skip (InterposeFirst s1)
2608 -}
2610 step _ (InterposeFirstInner s1 i1) = do
2611 r <- istep1 i1
2612 return $ case r of
2613 Yield x i' -> Yield x (InterposeFirstInner s1 i')
2614 Skip i' -> Skip (InterposeFirstInner s1 i')
2615 Stop -> Skip (InterposeFirstInject s1)
2617 step gst (InterposeFirstInject s1) = do
2618 r <- step1 (adaptState gst) s1
2619 case r of
2620 Yield a s -> do
2621 i <- inject1 a
2622 -- i `seq` return (Skip (InterposeFirstBuf s i))
2623 i `seq` return (Skip (InterposeSecondYield s i))
2624 Skip s -> return $ Skip (InterposeFirstInject s)
2625 Stop -> return Stop
2627 {-
2628 step _ (InterposeFirstBuf s1 i1) = do
2629 r <- istep1 i1
2630 return $ case r of
2631 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
2632 Skip i' -> Skip (InterposeFirstBuf s1 i')
2633 Stop -> Stop
2634 -}
2636 {-
2637 step _ (InterposeSecondYield s1 i1 v) = do
2638 r <- action
2639 return $ Yield r (InterposeFirstResume s1 i1 v)
2640 -}
2641 step _ (InterposeSecondYield s1 i1) = do
2642 r <- action
2643 return $ Yield r (InterposeFirstInner s1 i1)
2645 {-
2646 step _ (InterposeFirstResume s1 i1 v) = do
2647 return $ Yield v (InterposeFirstInner s1 i1)
2648 -}
2650------------------------------------------------------------------------------
2651-- Exceptions
2652------------------------------------------------------------------------------
2654data GbracketState s1 s2 v
2655 = GBracketInit
2656 | GBracketNormal s1 v
2657 | GBracketException s2
2659-- | The most general bracketing and exception combinator. All other
2660-- combinators can be expressed in terms of this combinator. This can also be
2661-- used for cases which are not covered by the standard combinators.
2663-- /Internal/
2665{-# INLINE_NORMAL gbracket #-}
2666gbracket
2667 :: Monad m
2668 => m c -- ^ before
2669 -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
2670 -> (c -> m d) -- ^ after, on normal stop
2671 -> (c -> e -> Stream m b) -- ^ on exception
2672 -> (c -> Stream m b) -- ^ stream generator
2673 -> Stream m b
2674gbracket bef exc aft fexc fnormal =
2675 Stream step GBracketInit
2677 where
2679 {-# INLINE_LATE step #-}
2680 step _ GBracketInit = do
2681 r <- bef
2682 return $ Skip $ GBracketNormal (fnormal r) r
2684 step gst (GBracketNormal (UnStream step1 st) v) = do
2685 res <- exc $ step1 gst st
2686 case res of
2687 Right r -> case r of
2688 Yield x s ->
2689 return $ Yield x (GBracketNormal (Stream step1 s) v)
2690 Skip s -> return $ Skip (GBracketNormal (Stream step1 s) v)
2691 Stop -> aft v >> return Stop
2692 Left e -> return $ Skip (GBracketException (fexc v e))
2693 step gst (GBracketException (UnStream step1 st)) = do
2694 res <- step1 gst st
2695 case res of
2696 Yield x s -> return $ Yield x (GBracketException (Stream step1 s))
2697 Skip s -> return $ Skip (GBracketException (Stream step1 s))
2698 Stop -> return Stop
2700-- | Run a side effect before the stream yields its first element.
2701{-# INLINE_NORMAL before #-}
2702before :: Monad m => m b -> Stream m a -> Stream m a
2703before action (Stream step state) = Stream step' Nothing
2705 where
2707 {-# INLINE_LATE step' #-}
2708 step' _ Nothing = action >> return (Skip (Just state))
2710 step' gst (Just st) = do
2711 res <- step gst st
2712 case res of
2713 Yield x s -> return $ Yield x (Just s)
2714 Skip s -> return $ Skip (Just s)
2715 Stop -> return Stop
2717-- | Run a side effect whenever the stream stops normally.
2718{-# INLINE_NORMAL after #-}
2719after :: Monad m => m b -> Stream m a -> Stream m a
2720after action (Stream step state) = Stream step' state
2722 where
2724 {-# INLINE_LATE step' #-}
2725 step' gst st = do
2726 res <- step gst st
2727 case res of
2728 Yield x s -> return $ Yield x s
2729 Skip s -> return $ Skip s
2730 Stop -> action >> return Stop
2732-- XXX These combinators are expensive due to the call to
2733-- onException/handle/try on each step. Therefore, when possible, they should
2734-- be called in an outer loop where we perform less iterations. For example, we
2735-- cannot call them on each iteration in a char stream, instead we can call
2736-- them when doing an IO on an array.
2738-- XXX For high performance error checks in busy streams we may need another
2739-- Error constructor in step.
2741-- | Run a side effect whenever the stream aborts due to an exception. The
2742-- exception is not caught, simply rethrown.
2743{-# INLINE_NORMAL onException #-}
2744onException :: MonadCatch m => m b -> Stream m a -> Stream m a
2745onException action str =
2746 gbracket (return ()) MC.try return
2747 (\_ (_ :: MC.SomeException) -> nilM $ action)
2748 (\_ -> str)
2750{-# INLINE_NORMAL _onException #-}
2751_onException :: MonadCatch m => m b -> Stream m a -> Stream m a
2752_onException action (Stream step state) = Stream step' state
2754 where
2756 {-# INLINE_LATE step' #-}
2757 step' gst st = do
2758 res <- step gst st `MC.onException` action
2759 case res of
2760 Yield x s -> return $ Yield x s
2761 Skip s -> return $ Skip s
2762 Stop -> return Stop
2764-- XXX bracket is like concatMap, it generates a stream and then flattens it.
2765-- Like concatMap it has 10x worse performance compared to linear fused
2766-- compositions.
2768-- | Run the first action before the stream starts and remember its output,
2769-- generate a stream using the output, run the second action providing the
2770-- remembered value as an argument whenever the stream ends normally or due to
2771-- an exception.
2772{-# INLINE_NORMAL bracket #-}
2773bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
2774bracket bef aft bet =
2775 gbracket bef MC.try aft (\a (_ :: SomeException) -> nilM $ aft a) bet
2777data BracketState s v = BracketInit | BracketRun s v
2779{-# INLINE_NORMAL _bracket #-}
2780_bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
2781_bracket bef aft bet = Stream step' BracketInit
2783 where
2785 {-# INLINE_LATE step' #-}
2786 step' _ BracketInit = bef >>= \x -> return (Skip (BracketRun (bet x) x))
2788 -- NOTE: It is important to use UnStream instead of the Stream pattern
2789 -- here, otherwise we get huge perf degradation, see note in concatMap.
2790 step' gst (BracketRun (UnStream step state) v) = do
2791 -- res <- step gst state `MC.onException` aft v
2792 res <- MC.try $ step gst state
2793 case res of
2794 Left (_ :: SomeException) -> aft v >> return Stop
2795 Right r -> case r of
2796 Yield x s -> return $ Yield x (BracketRun (Stream step s) v)
2797 Skip s -> return $ Skip (BracketRun (Stream step s) v)
2798 Stop -> aft v >> return Stop
2800-- | Run a side effect whenever the stream stops normally or aborts due to an
2801-- exception.
2802{-# INLINE finally #-}
2803finally :: MonadCatch m => m b -> Stream m a -> Stream m a
2804-- finally action xs = after action $ onException action xs
2805finally action xs = bracket (return ()) (\_ -> action) (const xs)
2807-- | When evaluating a stream if an exception occurs, stream evaluation aborts
2808-- and the specified exception handler is run with the exception as argument.
2809{-# INLINE_NORMAL handle #-}
2810handle :: (MonadCatch m, Exception e)
2811 => (e -> Stream m a) -> Stream m a -> Stream m a
2812handle f str =
2813 gbracket (return ()) MC.try return (\_ e -> f e) (\_ -> str)
2815{-# INLINE_NORMAL _handle #-}
2816_handle :: (MonadCatch m, Exception e)
2817 => (e -> Stream m a) -> Stream m a -> Stream m a
2818_handle f (Stream step state) = Stream step' (Left state)
2820 where
2822 {-# INLINE_LATE step' #-}
2823 step' gst (Left st) = do
2824 res <- MC.try $ step gst st
2825 case res of
2826 Left e -> return $ Skip $ Right (f e)
2827 Right r -> case r of
2828 Yield x s -> return $ Yield x (Left s)
2829 Skip s -> return $ Skip (Left s)
2830 Stop -> return Stop
2832 step' gst (Right (UnStream step1 st)) = do
2833 res <- step1 gst st
2834 case res of
2835 Yield x s -> return $ Yield x (Right (Stream step1 s))
2836 Skip s -> return $ Skip (Right (Stream step1 s))
2837 Stop -> return Stop
2839-------------------------------------------------------------------------------
2840-- General transformation
2841-------------------------------------------------------------------------------
2843{-# INLINE_NORMAL transform #-}
2844transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
2845transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
2846 Stream step' (Consume pstate, state)
2848 where
2850 {-# INLINE_LATE step' #-}
2852 step' gst (Consume pst, st) = pst `seq` do
2853 r <- step (adaptState gst) st
2854 case r of
2855 Yield x s -> do
2856 res <- pstep1 pst x
2857 case res of
2858 Pipe.Yield b pst' -> return $ Yield b (pst', s)
2859 Pipe.Continue pst' -> return $ Skip (pst', s)
2860 Skip s -> return $ Skip (Consume pst, s)
2861 Stop -> return Stop
2863 step' _ (Produce pst, st) = pst `seq` do
2864 res <- pstep2 pst
2865 case res of
2866 Pipe.Yield b pst' -> return $ Yield b (pst', st)
2867 Pipe.Continue pst' -> return $ Skip (pst', st)
2869------------------------------------------------------------------------------
2870-- Transformation by Folding (Scans)
2871------------------------------------------------------------------------------
2873------------------------------------------------------------------------------
2874-- Prescans
2875------------------------------------------------------------------------------
2877-- XXX Is a prescan useful, discarding the last step does not sound useful? I
2878-- am not sure about the utility of this function, so this is implemented but
2879-- not exposed. We can expose it if someone provides good reasons why this is
2880-- useful.
2882-- XXX We have to execute the stream one step ahead to know that we are at the
2883-- last step. The vector implementation of prescan executes the last fold step
2884-- but does not yield the result. This means we have executed the effect but
2885-- discarded value. This does not sound right. In this implementation we are
2886-- not executing the last fold step.
2887{-# INLINE_NORMAL prescanlM' #-}
2888prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
2889prescanlM' f mz (Stream step state) = Stream step' (state, mz)
2890 where
2891 {-# INLINE_LATE step' #-}
2892 step' gst (st, prev) = do
2893 r <- step (adaptState gst) st
2894 case r of
2895 Yield x s -> do
2896 acc <- prev
2897 return $ Yield acc (s, f acc x)
2898 Skip s -> return $ Skip (s, prev)
2899 Stop -> return Stop
2901{-# INLINE prescanl' #-}
2902prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2903prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
2905------------------------------------------------------------------------------
2906-- Monolithic postscans (postscan followed by a map)
2907------------------------------------------------------------------------------
2909-- The performance of a modular postscan followed by a map seems to be
2910-- equivalent to this monolithic scan followed by map therefore we may not need
2911-- this implementation. We just have it for performance comparison and in case
2912-- modular version does not perform well in some situation.
2914{-# INLINE_NORMAL postscanlMx' #-}
2915postscanlMx' :: Monad m
2916 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
2917postscanlMx' fstep begin done (Stream step state) = do
2918 Stream step' (state, begin)
2919 where
2920 {-# INLINE_LATE step' #-}
2921 step' gst (st, acc) = do
2922 r <- step (adaptState gst) st
2923 case r of
2924 Yield x s -> do
2925 old <- acc
2926 y <- fstep old x
2927 v <- done y
2928 v `seq` y `seq` return (Yield v (s, return y))
2929 Skip s -> return $ Skip (s, acc)
2930 Stop -> return Stop
2932{-# INLINE_NORMAL postscanlx' #-}
2933postscanlx' :: Monad m
2934 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
2935postscanlx' fstep begin done s =
2936 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
2938-- XXX do we need consM strict to evaluate the begin value?
2939{-# INLINE scanlMx' #-}
2940scanlMx' :: Monad m
2941 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
2942scanlMx' fstep begin done s =
2943 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
2945{-# INLINE scanlx' #-}
2946scanlx' :: Monad m
2947 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
2948scanlx' fstep begin done s =
2949 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
2951------------------------------------------------------------------------------
2952-- postscans
2953------------------------------------------------------------------------------
2955{-# INLINE_NORMAL postscanlM' #-}
2956postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2957postscanlM' fstep begin (Stream step state) =
2958 begin `seq` Stream step' (state, begin)
2959 where
2960 {-# INLINE_LATE step' #-}
2961 step' gst (st, acc) = acc `seq` do
2962 r <- step (adaptState gst) st
2963 case r of
2964 Yield x s -> do
2965 y <- fstep acc x
2966 y `seq` return (Yield y (s, y))
2967 Skip s -> return $ Skip (s, acc)
2968 Stop -> return Stop
2970{-# INLINE_NORMAL postscanl' #-}
2971postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
2972postscanl' f = postscanlM' (\a b -> return (f a b))
2974{-# INLINE_NORMAL postscanlM #-}
2975postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2976postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
2977 where
2978 {-# INLINE_LATE step' #-}
2979 step' gst (st, acc) = do
2980 r <- step (adaptState gst) st
2981 case r of
2982 Yield x s -> do
2983 y <- fstep acc x
2984 return (Yield y (s, y))
2985 Skip s -> return $ Skip (s, acc)
2986 Stop -> return Stop
2988{-# INLINE_NORMAL postscanl #-}
2989postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
2990postscanl f = postscanlM (\a b -> return (f a b))
2992{-# INLINE_NORMAL scanlM' #-}
2993scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
2994scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
2996{-# INLINE scanl' #-}
2997scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
2998scanl' f = scanlM' (\a b -> return (f a b))
3000{-# INLINE_NORMAL scanlM #-}
3001scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3002scanlM fstep begin s = begin `cons` postscanlM fstep begin s
3004{-# INLINE scanl #-}
3005scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3006scanl f = scanlM (\a b -> return (f a b))
3008{-# INLINE_NORMAL scanl1M #-}
3009scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3010scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
3011 where
3012 {-# INLINE_LATE step' #-}
3013 step' gst (st, Nothing) = do
3014 r <- step gst st
3015 case r of
3016 Yield x s -> return $ Yield x (s, Just x)
3017 Skip s -> return $ Skip (s, Nothing)
3018 Stop -> return Stop
3020 step' gst (st, Just acc) = do
3021 r <- step gst st
3022 case r of
3023 Yield y s -> do
3024 z <- fstep acc y
3025 return $ Yield z (s, Just z)
3026 Skip s -> return $ Skip (s, Just acc)
3027 Stop -> return Stop
3029{-# INLINE scanl1 #-}
3030scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3031scanl1 f = scanl1M (\x y -> return (f x y))
3033{-# INLINE_NORMAL scanl1M' #-}
3034scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3035scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
3036 where
3037 {-# INLINE_LATE step' #-}
3038 step' gst (st, Nothing) = do
3039 r <- step gst st
3040 case r of
3041 Yield x s -> x `seq` return $ Yield x (s, Just x)
3042 Skip s -> return $ Skip (s, Nothing)
3043 Stop -> return Stop
3045 step' gst (st, Just acc) = acc `seq` do
3046 r <- step gst st
3047 case r of
3048 Yield y s -> do
3049 z <- fstep acc y
3050 z `seq` return $ Yield z (s, Just z)
3051 Skip s -> return $ Skip (s, Just acc)
3052 Stop -> return Stop
3054{-# INLINE scanl1' #-}
3055scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3056scanl1' f = scanl1M' (\x y -> return (f x y))
3058{-# INLINE tap #-}
3059tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
3060tap (Fold fstep initial extract) (Stream step state) = Stream step' Nothing
3062 where
3064 step' _ Nothing = do
3065 r <- initial
3066 return $ Skip (Just (r, state))
3068 step' gst (Just (acc, st)) = do
3069 r <- step gst st
3070 case r of
3071 Yield x s -> do
3072 acc' <- fstep acc x
3073 return $ Yield x (Just (acc', s))
3074 Skip s -> return $ Skip (Just (acc, s))
3075 Stop -> do
3076 void $ extract acc
3077 return $ Stop
3079-------------------------------------------------------------------------------
3080-- Filtering
3081-------------------------------------------------------------------------------
3083{-# INLINE_NORMAL takeWhileM #-}
3084takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3085takeWhileM f (Stream step state) = Stream step' state
3086 where
3087 {-# INLINE_LATE step' #-}
3088 step' gst st = do
3089 r <- step gst st
3090 case r of
3091 Yield x s -> do
3092 b <- f x
3093 return $ if b then Yield x s else Stop
3094 Skip s -> return $ Skip s
3095 Stop -> return Stop
3097{-# INLINE takeWhile #-}
3098takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3099takeWhile f = takeWhileM (return . f)
3101{-# INLINE_NORMAL drop #-}
3102drop :: Monad m => Int -> Stream m a -> Stream m a
3103drop n (Stream step state) = Stream step' (state, Just n)
3104 where
3105 {-# INLINE_LATE step' #-}
3106 step' gst (st, Just i)
3107 | i > 0 = do
3108 r <- step gst st
3109 return $
3110 case r of
3111 Yield _ s -> Skip (s, Just (i - 1))
3112 Skip s -> Skip (s, Just i)
3113 Stop -> Stop
3114 | otherwise = return $ Skip (st, Nothing)
3116 step' gst (st, Nothing) = do
3117 r <- step gst st
3118 return $
3119 case r of
3120 Yield x s -> Yield x (s, Nothing)
3121 Skip s -> Skip (s, Nothing)
3122 Stop -> Stop
3124data DropWhileState s a
3125 = DropWhileDrop s
3126 | DropWhileYield a s
3127 | DropWhileNext s
3129{-# INLINE_NORMAL dropWhileM #-}
3130dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3131dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
3132 where
3133 {-# INLINE_LATE step' #-}
3134 step' gst (DropWhileDrop st) = do
3135 r <- step gst st
3136 case r of
3137 Yield x s -> do
3138 b <- f x
3139 if b
3140 then return $ Skip (DropWhileDrop s)
3141 else return $ Skip (DropWhileYield x s)
3142 Skip s -> return $ Skip (DropWhileDrop s)
3143 Stop -> return Stop
3145 step' gst (DropWhileNext st) = do
3146 r <- step gst st
3147 case r of
3148 Yield x s -> return $ Skip (DropWhileYield x s)
3149 Skip s -> return $ Skip (DropWhileNext s)
3150 Stop -> return Stop
3152 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
3154{-# INLINE dropWhile #-}
3155dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3156dropWhile f = dropWhileM (return . f)
3158{-# INLINE_NORMAL filterM #-}
3159filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3160filterM f (Stream step state) = Stream step' state
3161 where
3162 {-# INLINE_LATE step' #-}
3163 step' gst st = do
3164 r <- step gst st
3165 case r of
3166 Yield x s -> do
3167 b <- f x
3168 return $ if b
3169 then Yield x s
3170 else Skip s
3171 Skip s -> return $ Skip s
3172 Stop -> return Stop
3174{-# INLINE filter #-}
3175filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3176filter f = filterM (return . f)
3178{-# INLINE_NORMAL uniq #-}
3179uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
3180uniq (Stream step state) = Stream step' (Nothing, state)
3181 where
3182 {-# INLINE_LATE step' #-}
3183 step' gst (Nothing, st) = do
3184 r <- step gst st
3185 case r of
3186 Yield x s -> return $ Yield x (Just x, s)
3187 Skip s -> return $ Skip (Nothing, s)
3188 Stop -> return Stop
3189 step' gst (Just x, st) = do
3190 r <- step gst st
3191 case r of
3192 Yield y s | x == y -> return $ Skip (Just x, s)
3193 | otherwise -> return $ Yield y (Just y, s)
3194 Skip s -> return $ Skip (Just x, s)
3195 Stop -> return Stop
3197------------------------------------------------------------------------------
3198-- Transformation by Mapping
3199------------------------------------------------------------------------------
3201{-# INLINE_NORMAL sequence #-}
3202sequence :: Monad m => Stream m (m a) -> Stream m a
3203sequence (Stream step state) = Stream step' state
3204 where
3205 {-# INLINE_LATE step' #-}
3206 step' gst st = do
3207 r <- step (adaptState gst) st
3208 case r of
3209 Yield x s -> x >>= \a -> return (Yield a s)
3210 Skip s -> return $ Skip s
3211 Stop -> return Stop
3213------------------------------------------------------------------------------
3214-- Inserting
3215------------------------------------------------------------------------------
3217data LoopState x s = FirstYield s
3218 | InterspersingYield s
3219 | YieldAndCarry x s
3221{-# INLINE_NORMAL intersperseM #-}
3222intersperseM :: Monad m => m a -> Stream m a -> Stream m a
3223intersperseM m (Stream step state) = Stream step' (FirstYield state)
3224 where
3225 {-# INLINE_LATE step' #-}
3226 step' gst (FirstYield st) = do
3227 r <- step gst st
3228 return $
3229 case r of
3230 Yield x s -> Skip (YieldAndCarry x s)
3231 Skip s -> Skip (FirstYield s)
3232 Stop -> Stop
3234 step' gst (InterspersingYield st) = do
3235 r <- step gst st
3236 case r of
3237 Yield x s -> do
3238 a <- m
3239 return $ Yield a (YieldAndCarry x s)
3240 Skip s -> return $ Skip $ InterspersingYield s
3241 Stop -> return Stop
3243 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
3245data SuffixState s a
3246 = SuffixElem s
3247 | SuffixSuffix s
3248 | SuffixYield a (SuffixState s a)
3250{-# INLINE_NORMAL intersperseSuffix #-}
3251intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
3252intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
3253 where
3254 {-# INLINE_LATE step' #-}
3255 step' gst (SuffixElem st) = do
3256 r <- step gst st
3257 return $ case r of
3258 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
3259 Skip s -> Skip (SuffixElem s)
3260 Stop -> Stop
3262 step' _ (SuffixSuffix st) = do
3263 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
3265 step' _ (SuffixYield x next) = return $ Yield x next
3267{-# INLINE intersperse #-}
3268intersperse :: Monad m => a -> Stream m a -> Stream m a
3269intersperse a = intersperseM (return a)
3271{-# INLINE_NORMAL insertBy #-}
3272insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
3273insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
3274 where
3275 {-# INLINE_LATE step' #-}
3276 step' gst (st, False, _) = do
3277 r <- step gst st
3278 case r of
3279 Yield x s -> case cmp a x of
3280 GT -> return $ Yield x (s, False, Nothing)
3281 _ -> return $ Yield a (s, True, Just x)
3282 Skip s -> return $ Skip (s, False, Nothing)
3283 Stop -> return $ Yield a (st, True, Nothing)
3285 step' _ (_, True, Nothing) = return Stop
3287 step' gst (st, True, Just prev) = do
3288 r <- step gst st
3289 case r of
3290 Yield x s -> return $ Yield prev (s, True, Just x)
3291 Skip s -> return $ Skip (s, True, Just prev)
3292 Stop -> return $ Yield prev (st, True, Nothing)
3294------------------------------------------------------------------------------
3295-- Deleting
3296------------------------------------------------------------------------------
3298{-# INLINE_NORMAL deleteBy #-}
3299deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
3300deleteBy eq x (Stream step state) = Stream step' (state, False)
3301 where
3302 {-# INLINE_LATE step' #-}
3303 step' gst (st, False) = do
3304 r <- step gst st
3305 case r of
3306 Yield y s -> return $
3307 if eq x y then Skip (s, True) else Yield y (s, False)
3308 Skip s -> return $ Skip (s, False)
3309 Stop -> return Stop
3311 step' gst (st, True) = do
3312 r <- step gst st
3313 case r of
3314 Yield y s -> return $ Yield y (s, True)
3315 Skip s -> return $ Skip (s, True)
3316 Stop -> return Stop
3318------------------------------------------------------------------------------
3319-- Transformation by Map and Filter
3320------------------------------------------------------------------------------
3322-- XXX Will this always fuse properly?
3323{-# INLINE_NORMAL mapMaybe #-}
3324mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
3325mapMaybe f = fmap fromJust . filter isJust . map f
3327{-# INLINE_NORMAL mapMaybeM #-}
3328mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
3329mapMaybeM f = fmap fromJust . filter isJust . mapM f
3331------------------------------------------------------------------------------
3332-- Zipping
3333------------------------------------------------------------------------------
3335{-# INLINE_NORMAL indexed #-}
3336indexed :: Monad m => Stream m a -> Stream m (Int, a)
3337indexed (Stream step state) = Stream step' (state, 0)
3338 where
3339 {-# INLINE_LATE step' #-}
3340 step' gst (st, i) = i `seq` do
3341 r <- step (adaptState gst) st
3342 case r of
3343 Yield x s -> return $ Yield (i, x) (s, i+1)
3344 Skip s -> return $ Skip (s, i)
3345 Stop -> return Stop
3347{-# INLINE_NORMAL indexedR #-}
3348indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
3349indexedR m (Stream step state) = Stream step' (state, m)
3350 where
3351 {-# INLINE_LATE step' #-}
3352 step' gst (st, i) = i `seq` do
3353 r <- step (adaptState gst) st
3354 case r of
3355 Yield x s -> let i' = i - 1
3356 in return $ Yield (i, x) (s, i')
3357 Skip s -> return $ Skip (s, i)
3358 Stop -> return Stop
3360{-# INLINE_NORMAL zipWithM #-}
3361zipWithM :: Monad m
3362 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
3363zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
3364 where
3365 {-# INLINE_LATE step #-}
3366 step gst (sa, sb, Nothing) = do
3367 r <- stepa (adaptState gst) sa
3368 return $
3369 case r of
3370 Yield x sa' -> Skip (sa', sb, Just x)
3371 Skip sa' -> Skip (sa', sb, Nothing)
3372 Stop -> Stop
3374 step gst (sa, sb, Just x) = do
3375 r <- stepb (adaptState gst) sb
3376 case r of
3377 Yield y sb' -> do
3378 z <- f x y
3379 return $ Yield z (sa, sb', Nothing)
3380 Skip sb' -> return $ Skip (sa, sb', Just x)
3381 Stop -> return Stop
3383#if __GLASGOW_HASKELL__ >= 801
3384{-# RULES "zipWithM xs xs"
3385 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
3386#endif
3388{-# INLINE zipWith #-}
3389zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
3390zipWith f = zipWithM (\a b -> return (f a b))
3392------------------------------------------------------------------------------
3393-- Merging
3394------------------------------------------------------------------------------
3396{-# INLINE_NORMAL mergeByM #-}
3397mergeByM
3398 :: (Monad m)
3399 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
3400mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
3401 Stream step (Just ta, Just tb, Nothing, Nothing)
3402 where
3403 {-# INLINE_LATE step #-}
3405 -- one of the values is missing, and the corresponding stream is running
3406 step gst (Just sa, sb, Nothing, b) = do
3407 r <- stepa gst sa
3408 return $ case r of
3409 Yield a sa' -> Skip (Just sa', sb, Just a, b)
3410 Skip sa' -> Skip (Just sa', sb, Nothing, b)
3411 Stop -> Skip (Nothing, sb, Nothing, b)
3413 step gst (sa, Just sb, a, Nothing) = do
3414 r <- stepb gst sb
3415 return $ case r of
3416 Yield b sb' -> Skip (sa, Just sb', a, Just b)
3417 Skip sb' -> Skip (sa, Just sb', a, Nothing)
3418 Stop -> Skip (sa, Nothing, a, Nothing)
3420 -- both the values are available
3421 step _ (sa, sb, Just a, Just b) = do
3422 res <- cmp a b
3423 return $ case res of
3424 GT -> Yield b (sa, sb, Just a, Nothing)
3425 _ -> Yield a (sa, sb, Nothing, Just b)
3427 -- one of the values is missing, corresponding stream is done
3428 step _ (Nothing, sb, Nothing, Just b) =
3429 return $ Yield b (Nothing, sb, Nothing, Nothing)
3431 step _ (sa, Nothing, Just a, Nothing) =
3432 return $ Yield a (sa, Nothing, Nothing, Nothing)
3434 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
3436{-# INLINE mergeBy #-}
3437mergeBy
3438 :: (Monad m)
3439 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
3440mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
3442------------------------------------------------------------------------------
3443-- Transformation comprehensions
3444------------------------------------------------------------------------------
3446{-# INLINE_NORMAL the #-}
3447the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
3448the (Stream step state) = go state
3449 where
3450 go st = do
3451 r <- step defState st
3452 case r of
3453 Yield x s -> go' x s
3454 Skip s -> go s
3455 Stop -> return Nothing
3456 go' n st = do
3457 r <- step defState st
3458 case r of
3459 Yield x s | x == n -> go' n s
3460 | otherwise -> return Nothing
3461 Skip s -> go' n s
3462 Stop -> return (Just n)
3464--------------------------------------------------------------------------------
3465-- UTF8 Encoding / Decoding
3466--------------------------------------------------------------------------------
3468-- UTF-8 primitives, Lifted from GHC.IO.Encoding.UTF8.
3470{-# INLINE ord2 #-}
3471ord2 :: Char -> WList
3472ord2 c = assert (n >= 0x80 && n <= 0x07ff) (WCons x1 (WCons x2 WNil))
3473 where
3474 n = ord c
3475 x1 = fromIntegral $ (n `shiftR` 6) + 0xC0
3476 x2 = fromIntegral $ (n .&. 0x3F) + 0x80
3478{-# INLINE ord3 #-}
3479ord3 :: Char -> WList
3480ord3 c = assert (n >= 0x0800 && n <= 0xffff) (WCons x1 (WCons x2 (WCons x3 WNil)))
3481 where
3482 n = ord c
3483 x1 = fromIntegral $ (n `shiftR` 12) + 0xE0
3484 x2 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80
3485 x3 = fromIntegral $ (n .&. 0x3F) + 0x80
3487{-# INLINE ord4 #-}
3488ord4 :: Char -> WList
3489ord4 c = assert (n >= 0x10000) (WCons x1 (WCons x2 (WCons x3 (WCons x4 WNil))))
3490 where
3491 n = ord c
3492 x1 = fromIntegral $ (n `shiftR` 18) + 0xF0
3493 x2 = fromIntegral $ ((n `shiftR` 12) .&. 0x3F) + 0x80
3494 x3 = fromIntegral $ ((n `shiftR` 6) .&. 0x3F) + 0x80
3495 x4 = fromIntegral $ (n .&. 0x3F) + 0x80
3497data CodingFailureMode
3498 = TransliterateCodingFailure
3499 | ErrorOnCodingFailure
3500 deriving (Show)
3502{-# INLINE replacementChar #-}
3503replacementChar :: Char
3504replacementChar = '\xFFFD'
3506-- Int helps in cheaper conversion from Int to Char
3507type CodePoint = Int
3508type DecodeState = Word8
3510-- See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
3512{-# INLINE runFold #-}
3513runFold :: (Monad m) => Fold m a b -> Stream m a -> m b
3514runFold (Fold step begin done) = foldlMx' step begin done
3516-- XXX Use names decodeSuccess = 0, decodeFailure = 12
3518decodeTable :: [Word8]
3519decodeTable = [
3520 -- The first part of the table maps bytes to character classes that
3521 -- to reduce the size of the transition table and create bitmasks.
3522 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3523 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3524 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3525 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3526 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
3527 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
3528 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3529 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
3531 -- The second part is a transition table that maps a combination
3532 -- of a state of the automaton and a character class to a state.
3533 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
3534 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
3535 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
3536 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
3537 12,36,12,12,12,12,12,12,12,12,12,12
3540utf8d :: A.Array Word8
3541utf8d =
3542 unsafePerformIO
3543 -- Aligning to cacheline makes a barely noticeable difference
3544 -- XXX currently alignment is not implemented for unmanaged allocation
3545 $ runFold (A.writeNAlignedUnmanaged 64 (length decodeTable))
3546 (fromList decodeTable)
3548-- | Return element at the specified index without checking the bounds.
3549-- and without touching the foreign ptr.
3550{-# INLINE_NORMAL unsafePeekElemOff #-}
3551unsafePeekElemOff :: forall a. Storable a => Ptr a -> Int -> a
3552unsafePeekElemOff p i = let !x = A.unsafeInlineIO $ peekElemOff p i in x
3554-- decode is split into two separate cases to avoid branching instructions.
3555-- From the higher level flow we already know which case we are in so we can
3556-- call the appropriate decode function.
3558-- When the state is 0
3559{-# INLINE decode0 #-}
3560decode0 :: Ptr Word8 -> Word8 -> Tuple' DecodeState CodePoint
3561decode0 table byte =
3562 let !t = table `unsafePeekElemOff` fromIntegral byte
3563 !codep' = (0xff `shiftR` (fromIntegral t)) .&. fromIntegral byte
3564 !state' = table `unsafePeekElemOff` (256 + fromIntegral t)
3565 in assert ((byte > 0x7f || error showByte)
3566 && (state' /= 0 || error (showByte ++ showTable)))
3567 (Tuple' state' codep')
3569 where
3571 utf8table =
3572 let !(Ptr addr) = table
3573 end = table `plusPtr` 364
3574 in A.Array (ForeignPtr addr undefined) end end :: A.Array Word8
3575 showByte = "Streamly: decode0: byte: " ++ show byte
3576 showTable = " table: " ++ show utf8table
3578-- When the state is not 0
3579{-# INLINE decode1 #-}
3580decode1
3581 :: Ptr Word8
3582 -> DecodeState
3583 -> CodePoint
3584 -> Word8
3585 -> Tuple' DecodeState CodePoint
3586decode1 table state codep byte =
3587 -- Remember codep is Int type!
3588 -- Can it be unsafe to convert the resulting Int to Char?
3589 let !t = table `unsafePeekElemOff` fromIntegral byte
3590 !codep' = (fromIntegral byte .&. 0x3f) .|. (codep `shiftL` 6)
3591 !state' = table `unsafePeekElemOff`
3592 (256 + fromIntegral state + fromIntegral t)
3593 in assert (codep' <= 0x10FFFF
3594 || error (showByte ++ showState state codep))
3595 (Tuple' state' codep')
3596 where
3598 utf8table =
3599 let !(Ptr addr) = table
3600 end = table `plusPtr` 364
3601 in A.Array (ForeignPtr addr undefined) end end :: A.Array Word8
3602 showByte = "Streamly: decode1: byte: " ++ show byte
3603 showState st cp =
3604 " state: " ++ show st ++
3605 " codepoint: " ++ show cp ++
3606 " table: " ++ show utf8table
3608-- We can divide the errors in three general categories:
3609-- * A non-starter was encountered in a begin state
3610-- * A starter was encountered without completing a codepoint
3611-- * The last codepoint was not complete (input underflow)
3613data DecodeError = DecodeError !DecodeState !CodePoint deriving Show
3615data FreshPoint s a
3616 = FreshPointDecodeInit s
3617 | FreshPointDecodeInit1 s Word8
3618 | FreshPointDecodeFirst s Word8
3619 | FreshPointDecoding s !DecodeState !CodePoint
3620 | YieldAndContinue a (FreshPoint s a)
3621 | Done
3623-- XXX Add proper error messages
3624-- XXX Implement this in terms of decodeUtf8Either
3625{-# INLINE_NORMAL decodeUtf8With #-}
3626decodeUtf8With :: Monad m => CodingFailureMode -> Stream m Word8 -> Stream m Char
3627decodeUtf8With cfm (Stream step state) =
3628 let Array p _ _ = utf8d
3629 !ptr = (unsafeForeignPtrToPtr p)
3630 in Stream (step' ptr) (FreshPointDecodeInit state)
3631 where
3632 {-# INLINE transliterateOrError #-}
3633 transliterateOrError e s =
3634 case cfm of
3635 ErrorOnCodingFailure -> error e
3636 TransliterateCodingFailure -> YieldAndContinue replacementChar s
3637 {-# INLINE inputUnderflow #-}
3638 inputUnderflow =
3639 case cfm of
3640 ErrorOnCodingFailure ->
3641 error "Streamly.Streams.StreamD.decodeUtf8With: Input Underflow"
3642 TransliterateCodingFailure -> YieldAndContinue replacementChar Done
3643 {-# INLINE_LATE step' #-}
3644 step' _ gst (FreshPointDecodeInit st) = do
3645 r <- step (adaptState gst) st
3646 return $ case r of
3647 Yield x s -> Skip (FreshPointDecodeInit1 s x)
3648 Skip s -> Skip (FreshPointDecodeInit s)
3649 Stop -> Skip Done
3651 step' _ _ (FreshPointDecodeInit1 st x) = do
3652 -- Note: It is important to use a ">" instead of a "<=" test
3653 -- here for GHC to generate code layout for default branch
3654 -- prediction for the common case. This is fragile and might
3655 -- change with the compiler versions, we need a more reliable
3656 -- "likely" primitive to control branch predication.
3657 case x > 0x7f of
3658 False ->
3659 return $ Skip $ YieldAndContinue
3660 (unsafeChr (fromIntegral x))
3661 (FreshPointDecodeInit st)
3662 -- Using a separate state here generates a jump to a
3663 -- separate code block in the core which seems to perform
3664 -- slightly better for the non-ascii case.
3665 True -> return $ Skip $ FreshPointDecodeFirst st x
3667 -- XXX should we merge it with FreshPointDecodeInit1?
3668 step' table _ (FreshPointDecodeFirst st x) = do
3669 let (Tuple' sv cp) = decode0 table x
3670 return $
3671 case sv of
3672 12 ->
3673 Skip $
3674 transliterateOrError
3675 "Streamly.Streams.StreamD.decodeUtf8With: Invalid UTF8 codepoint encountered"
3676 (FreshPointDecodeInit st)
3677 0 -> error "unreachable state"
3678 _ -> Skip (FreshPointDecoding st sv cp)
3680 -- We recover by trying the new byte x a starter of a new codepoint.
3681 -- XXX need to use the same recovery in array decoding routine as well
3682 step' table gst (FreshPointDecoding st statePtr codepointPtr) = do
3683 r <- step (adaptState gst) st
3684 case r of
3685 Yield x s -> do
3686 let (Tuple' sv cp) = decode1 table statePtr codepointPtr x
3687 return $
3688 case sv of
3689 0 -> Skip $ YieldAndContinue (unsafeChr cp)
3690 (FreshPointDecodeInit s)
3691 12 ->
3692 Skip $
3693 transliterateOrError
3694 "Streamly.Streams.StreamD.decodeUtf8With: Invalid UTF8 codepoint encountered"
3695 (FreshPointDecodeInit1 s x)
3696 _ -> Skip (FreshPointDecoding s sv cp)
3697 Skip s -> return $ Skip (FreshPointDecoding s statePtr codepointPtr)
3698 Stop -> return $ Skip inputUnderflow
3700 step' _ _ (YieldAndContinue c s) = return $ Yield c s
3701 step' _ _ Done = return Stop
3703{-# INLINE decodeUtf8 #-}
3704decodeUtf8 :: Monad m => Stream m Word8 -> Stream m Char
3705decodeUtf8 = decodeUtf8With ErrorOnCodingFailure
3707{-# INLINE decodeUtf8Lenient #-}
3708decodeUtf8Lenient :: Monad m => Stream m Word8 -> Stream m Char
3709decodeUtf8Lenient = decodeUtf8With TransliterateCodingFailure
3711{-# INLINE_NORMAL resumeDecodeUtf8Either #-}
3712resumeDecodeUtf8Either
3713 :: Monad m
3714 => DecodeState
3715 -> CodePoint
3716 -> Stream m Word8
3717 -> Stream m (Either DecodeError Char)
3718resumeDecodeUtf8Either dst codep (Stream step state) =
3719 let Array p _ _ = utf8d
3720 !ptr = (unsafeForeignPtrToPtr p)
3721 stt =
3722 if dst == 0
3723 then FreshPointDecodeInit state
3724 else FreshPointDecoding state dst codep
3725 in Stream (step' ptr) stt
3726 where
3727 {-# INLINE_LATE step' #-}
3728 step' _ gst (FreshPointDecodeInit st) = do
3729 r <- step (adaptState gst) st
3730 return $ case r of
3731 Yield x s -> Skip (FreshPointDecodeInit1 s x)
3732 Skip s -> Skip (FreshPointDecodeInit s)
3733 Stop -> Skip Done
3735 step' _ _ (FreshPointDecodeInit1 st x) = do
3736 -- Note: It is important to use a ">" instead of a "<=" test
3737 -- here for GHC to generate code layout for default branch
3738 -- prediction for the common case. This is fragile and might
3739 -- change with the compiler versions, we need a more reliable
3740 -- "likely" primitive to control branch predication.
3741 case x > 0x7f of
3742 False ->
3743 return $ Skip $ YieldAndContinue
3744 (Right $ unsafeChr (fromIntegral x))
3745 (FreshPointDecodeInit st)
3746 -- Using a separate state here generates a jump to a
3747 -- separate code block in the core which seems to perform
3748 -- slightly better for the non-ascii case.
3749 True -> return $ Skip $ FreshPointDecodeFirst st x
3751 -- XXX should we merge it with FreshPointDecodeInit1?
3752 step' table _ (FreshPointDecodeFirst st x) = do
3753 let (Tuple' sv cp) = decode0 table x
3754 return $
3755 case sv of
3756 12 ->
3757 Skip $ YieldAndContinue (Left $ DecodeError 0 (fromIntegral x))
3758 (FreshPointDecodeInit st)
3759 0 -> error "unreachable state"
3760 _ -> Skip (FreshPointDecoding st sv cp)
3762 -- We recover by trying the new byte x a starter of a new codepoint.
3763 -- XXX need to use the same recovery in array decoding routine as well
3764 step' table gst (FreshPointDecoding st statePtr codepointPtr) = do
3765 r <- step (adaptState gst) st
3766 case r of
3767 Yield x s -> do
3768 let (Tuple' sv cp) = decode1 table statePtr codepointPtr x
3769 return $
3770 case sv of
3771 0 -> Skip $ YieldAndContinue (Right $ unsafeChr cp)
3772 (FreshPointDecodeInit s)
3773 12 ->
3774 Skip $ YieldAndContinue (Left $ DecodeError statePtr codepointPtr)
3775 (FreshPointDecodeInit1 s x)
3776 _ -> Skip (FreshPointDecoding s sv cp)
3777 Skip s -> return $ Skip (FreshPointDecoding s statePtr codepointPtr)
3778 Stop -> return $ Skip $ YieldAndContinue (Left $ DecodeError statePtr codepointPtr) Done
3780 step' _ _ (YieldAndContinue c s) = return $ Yield c s
3781 step' _ _ Done = return Stop
3783{-# INLINE_NORMAL decodeUtf8Either #-}
3784decodeUtf8Either :: Monad m
3785 => Stream m Word8 -> Stream m (Either DecodeError Char)
3786decodeUtf8Either = resumeDecodeUtf8Either 0 0
3788data FlattenState s a
3789 = OuterLoop s !(Maybe (DecodeState, CodePoint))
3790 | InnerLoopDecodeInit s (ForeignPtr a) !(Ptr a) !(Ptr a)
3791 | InnerLoopDecodeFirst s (ForeignPtr a) !(Ptr a) !(Ptr a) Word8
3792 | InnerLoopDecoding s (ForeignPtr a) !(Ptr a) !(Ptr a)
3793 !DecodeState !CodePoint
3794 | YAndC !Char (FlattenState s a) -- These constructors can be
3795 -- encoded in the FreshPoint
3796 -- type, I prefer to keep these
3797 -- flat even though that means
3798 -- coming up with new names
3799 | D
3801-- The normal decodeUtf8 above should fuse with flattenArrays
3802-- to create this exact code but it doesn't for some reason, as of now this
3803-- remains the fastest way I could figure out to decodeUtf8.
3805-- XXX Add Proper error messages
3806{-# INLINE_NORMAL decodeUtf8ArraysWith #-}
3807decodeUtf8ArraysWith ::
3808 MonadIO m
3809 => CodingFailureMode
3810 -> Stream m (A.Array Word8)
3811 -> Stream m Char
3812decodeUtf8ArraysWith cfm (Stream step state) =
3813 let Array p _ _ = utf8d
3814 !ptr = (unsafeForeignPtrToPtr p)
3815 in Stream (step' ptr) (OuterLoop state Nothing)
3816 where
3817 {-# INLINE transliterateOrError #-}
3818 transliterateOrError e s =
3819 case cfm of
3820 ErrorOnCodingFailure -> error e
3821 TransliterateCodingFailure -> YAndC replacementChar s
3822 {-# INLINE inputUnderflow #-}
3823 inputUnderflow =
3824 case cfm of
3825 ErrorOnCodingFailure ->
3826 error
3827 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Input Underflow"
3828 TransliterateCodingFailure -> YAndC replacementChar D
3829 {-# INLINE_LATE step' #-}
3830 step' _ gst (OuterLoop st Nothing) = do
3831 r <- step (adaptState gst) st
3832 return $
3833 case r of
3834 Yield A.Array {..} s ->
3835 let p = unsafeForeignPtrToPtr aStart
3836 in Skip (InnerLoopDecodeInit s aStart p aEnd)
3837 Skip s -> Skip (OuterLoop s Nothing)
3838 Stop -> Skip D
3839 step' _ gst (OuterLoop st dst@(Just (ds, cp))) = do
3840 r <- step (adaptState gst) st
3841 return $
3842 case r of
3843 Yield A.Array {..} s ->
3844 let p = unsafeForeignPtrToPtr aStart
3845 in Skip (InnerLoopDecoding s aStart p aEnd ds cp)
3846 Skip s -> Skip (OuterLoop s dst)
3847 Stop -> Skip inputUnderflow
3848 step' _ _ (InnerLoopDecodeInit st startf p end)
3849 | p == end = do
3850 liftIO $ touchForeignPtr startf
3851 return $ Skip $ OuterLoop st Nothing
3852 step' _ _ (InnerLoopDecodeInit st startf p end) = do
3853 x <- liftIO $ peek p
3854 -- Note: It is important to use a ">" instead of a "<=" test here for
3855 -- GHC to generate code layout for default branch prediction for the
3856 -- common case. This is fragile and might change with the compiler
3857 -- versions, we need a more reliable "likely" primitive to control
3858 -- branch predication.
3859 case x > 0x7f of
3860 False ->
3861 return $ Skip $ YAndC
3862 (unsafeChr (fromIntegral x))
3863 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3864 -- Using a separate state here generates a jump to a separate code
3865 -- block in the core which seems to perform slightly better for the
3866 -- non-ascii case.
3867 True -> return $ Skip $ InnerLoopDecodeFirst st startf p end x
3869 step' table _ (InnerLoopDecodeFirst st startf p end x) = do
3870 let (Tuple' sv cp) = decode0 table x
3871 return $
3872 case sv of
3873 12 ->
3874 Skip $
3875 transliterateOrError
3876 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Invalid UTF8 codepoint encountered"
3877 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3878 0 -> error "unreachable state"
3879 _ -> Skip (InnerLoopDecoding st startf (p `plusPtr` 1) end sv cp)
3880 step' _ _ (InnerLoopDecoding st startf p end sv cp)
3881 | p == end = do
3882 liftIO $ touchForeignPtr startf
3883 return $ Skip $ OuterLoop st (Just (sv, cp))
3884 step' table _ (InnerLoopDecoding st startf p end statePtr codepointPtr) = do
3885 x <- liftIO $ peek p
3886 let (Tuple' sv cp) = decode1 table statePtr codepointPtr x
3887 return $
3888 case sv of
3889 0 ->
3890 Skip $
3891 YAndC
3892 (unsafeChr cp)
3893 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3894 12 ->
3895 Skip $
3896 transliterateOrError
3897 "Streamly.Streams.StreamD.decodeUtf8ArraysWith: Invalid UTF8 codepoint encountered"
3898 (InnerLoopDecodeInit st startf (p `plusPtr` 1) end)
3899 _ -> Skip (InnerLoopDecoding st startf (p `plusPtr` 1) end sv cp)
3900 step' _ _ (YAndC c s) = return $ Yield c s
3901 step' _ _ D = return Stop
3903{-# INLINE decodeUtf8Arrays #-}
3904decodeUtf8Arrays ::
3905 MonadIO m
3906 => Stream m (A.Array Word8)
3907 -> Stream m Char
3908decodeUtf8Arrays = decodeUtf8ArraysWith ErrorOnCodingFailure
3910{-# INLINE decodeUtf8ArraysLenient #-}
3911decodeUtf8ArraysLenient ::
3912 MonadIO m
3913 => Stream m (A.Array Word8)
3914 -> Stream m Char
3915decodeUtf8ArraysLenient = decodeUtf8ArraysWith TransliterateCodingFailure
3917data WList = WCons !Word8 !WList | WNil
3919data EncodeState s = EncodeState s !WList
3921-- More yield points improve performance, but I am not sure if they can cause
3922-- too much code bloat or some trouble with fusion. So keeping only two yield
3923-- points for now, one for the ascii chars (fast path) and one for all other
3924-- paths (slow path).
3925{-# INLINE_NORMAL encodeUtf8 #-}
3926encodeUtf8 :: Monad m => Stream m Char -> Stream m Word8
3927encodeUtf8 (Stream step state) = Stream step' (EncodeState state WNil)
3928 where
3929 {-# INLINE_LATE step' #-}
3930 step' gst (EncodeState st WNil) = do
3931 r <- step (adaptState gst) st
3932 return $
3933 case r of
3934 Yield c s ->
3935 case ord c of
3937 | x <= 0x7F ->
3938 Yield (fromIntegral x) (EncodeState s WNil)
3939 | x <= 0x7FF -> Skip (EncodeState s (ord2 c))
3940 | x <= 0xFFFF ->
3941 if isSurrogate c
3942 then error
3943 "Streamly.Streams.StreamD.encodeUtf8: Encountered a surrogate"
3944 else Skip (EncodeState s (ord3 c))
3945 | otherwise -> Skip (EncodeState s (ord4 c))
3946 Skip s -> Skip (EncodeState s WNil)
3947 Stop -> Stop
3948 step' _ (EncodeState s (WCons x xs)) = return $ Yield x (EncodeState s xs)