@@ -22,77 +22,22 @@ module Data.Text.Fusion
2222
2323 -- * Creation and elimination
2424 , stream
25− , streamList
2625 , unstream
27− , unstreamList
2826 , reverseStream
29− , empty
3027
31− -- * Basic interface
32− , cons
33− , snoc
34− , append
35− , uncons
36− , head
37− , tail
38− , last
39− , init
40− , null
4128 , length
42− , length64
4329
4430 -- * Transformations
45− , map
46− , intercalate
47− , intersperse
4831 , reverse
4932
50− -- * Folds
51− , foldl
52− , foldl'
53− , foldl1
54− , foldl1'
55− , foldr
56− , foldr1
57−
58− -- ** Special folds
59− , concat
60− , concatMap
61− , any
62− , all
63− , maximum
64− , minimum
65−
6633 -- * Construction
6734 -- ** Scans
68− , scanl
6935 , reverseScanr
7036
71− -- ** Accumulating maps
72− , mapAccumL
73−
7437 -- ** Generation and unfolding
75− , replicate
76− , unfoldr
7738 , unfoldrN
78− , unfoldrN64
79−
80− -- * Substrings
81− -- ** Breaking strings
82− , take
83− , drop
84− , takeWhile
85− , dropWhile
86−
87− -- * Predicates
88− , isPrefixOf
89−
90− -- * Searching
91− , elem
92− , filter
9339
9440 -- * Indexing
95− , find
9641 , index
9742 , findIndex
9843 , findIndices
@@ -100,22 +45,17 @@ module Data.Text.Fusion
10045 , elemIndex
10146 , elemIndices
10247 , count
103−
104− -- * Zipping and unzipping
105− , zipWith
10648 ) where
10749
108−import Prelude (Bool(..), Char, Either(..), Eq(..), Integral, Maybe(..),
109− Monad(..), Num(..), Ord(..), String, ($), (++), (.), (&&),
50+import Prelude (Bool(..), Char, Eq(..), Maybe(..), Monad(..), Int,
51+ Num(..), Ord(..), String, ($), (++), (&&),
11052 fromIntegral, otherwise)
111−import qualified Data.List as L
112−import GHC.Exts (Int(..), (+#))
11353import Data.Bits ((.&.), shiftR)
11454import Data.Char (ord)
115−import Data.Int (Int64)
11655import Data.Text.Internal (Text(..))
11756import Data.Text.UnsafeChar (unsafeChr, unsafeWrite)
11857import qualified Data.Text.Array as A
58+import qualified Data.Text.Fusion.Common as S
11959import Data.Text.Fusion.Internal
12060import qualified Data.Text.Internal as I
12161import qualified Data.Text.Encoding.Utf16 as U16
@@ -173,198 +113,14 @@ unstream (Stream next0 s0 len)
173113{-# INLINE [0] unstream #-}
174114{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
175115
176−streamError :: String -> String -> a
177−streamError func msg = P.error $ "Data.Text.Fusion." ++ func ++ ": " ++ msg
178−
179−internalError :: String -> a
180−internalError func = streamError func "Internal error"
181−
182−emptyError :: String -> a
183−emptyError func = internalError func "Empty input"
184116
185117-- ----------------------------------------------------------------------------
186118-- * Basic stream functions
187119
188−-- | /O(n)/ Adds a character to the front of a Stream Char.
189−cons :: Char -> Stream Char -> Stream Char
190−cons w (Stream next0 s0 len) = Stream next (S2 :!: s0) (len+2)
191− where
192− {-# INLINE next #-}
193− next (S2 :!: s) = Yield w (S1 :!: s)
194− next (S1 :!: s) = case next0 s of
195− Done -> Done
196− Skip s' -> Skip (S1 :!: s')
197− Yield x s' -> Yield x (S1 :!: s')
198−{-# INLINE [0] cons #-}
199−
200−-- | /O(n)/ Adds a character to the end of a stream.
201−snoc :: Stream Char -> Char -> Stream Char
202−snoc (Stream next0 xs0 len) w = Stream next (Just xs0) (len+2)
203− where
204− {-# INLINE next #-}
205− next (Just xs) = case next0 xs of
206− Done -> Yield w Nothing
207− Skip xs' -> Skip (Just xs')
208− Yield x xs' -> Yield x (Just xs')
209− next Nothing = Done
210−{-# INLINE [0] snoc #-}
211−
212−-- | /O(n)/ Appends one Stream to the other.
213−append :: Stream Char -> Stream Char -> Stream Char
214−append (Stream next0 s01 len1) (Stream next1 s02 len2) =
215− Stream next (Left s01) (len1 + len2)
216− where
217− {-# INLINE next #-}
218− next (Left s1) = case next0 s1 of
219− Done -> Skip (Right s02)
220− Skip s1' -> Skip (Left s1')
221− Yield x s1' -> Yield x (Left s1')
222− next (Right s2) = case next1 s2 of
223− Done -> Done
224− Skip s2' -> Skip (Right s2')
225− Yield x s2' -> Yield x (Right s2')
226−{-# INLINE [0] append #-}
227−
228−-- | /O(1)/ Returns the first character of a Text, which must be non-empty.
229−-- Subject to array fusion.
230−head :: Stream Char -> Char
231−head (Stream next s0 _len) = loop_head s0
232− where
233− loop_head !s = case next s of
234− Yield x _ -> x
235− Skip s' -> loop_head s'
236− Done -> streamError "head" "Empty stream"
237−{-# INLINE [0] head #-}
238−
239−-- | /O(1)/ Returns the first character and remainder of a 'Stream
240−-- Char', or 'Nothing' if empty. Subject to array fusion.
241−uncons :: Stream Char -> Maybe (Char, Stream Char)
242−uncons (Stream next s0 len) = loop_uncons s0
243− where
244− loop_uncons !s = case next s of
245− Yield x s1 -> Just (x, Stream next s1 (len-1))
246− Skip s' -> loop_uncons s'
247− Done -> Nothing
248−{-# INLINE [0] uncons #-}
249−
250−-- | /O(n)/ Returns the last character of a 'Stream Char', which must
251−-- be non-empty.
252−last :: Stream Char -> Char
253−last (Stream next s0 _len) = loop0_last s0
254− where
255− loop0_last !s = case next s of
256− Done -> emptyError "last"
257− Skip s' -> loop0_last s'
258− Yield x s' -> loop_last x s'
259− loop_last !x !s = case next s of
260− Done -> x
261− Skip s' -> loop_last x s'
262− Yield x' s' -> loop_last x' s'
263−{-# INLINE[0] last #-}
264−
265−-- | /O(1)/ Returns all characters after the head of a Stream Char, which must
266−-- be non-empty.
267−tail :: Stream Char -> Stream Char
268−tail (Stream next0 s0 len) = Stream next (False :!: s0) (len-1)
269− where
270− {-# INLINE next #-}
271− next (False :!: s) = case next0 s of
272− Done -> emptyError "tail"
273− Skip s' -> Skip (False :!: s')
274− Yield _ s' -> Skip (True :!: s')
275− next (True :!: s) = case next0 s of
276− Done -> Done
277− Skip s' -> Skip (True :!: s')
278− Yield x s' -> Yield x (True :!: s')
279−{-# INLINE [0] tail #-}
280−
281−
282−-- | /O(1)/ Returns all but the last character of a Stream Char, which
283−-- must be non-empty.
284−init :: Stream Char -> Stream Char
285−init (Stream next0 s0 len) = Stream next (Nothing :!: s0) (len-1)
286− where
287− {-# INLINE next #-}
288− next (Nothing :!: s) = case next0 s of
289− Done -> emptyError "init"
290− Skip s' -> Skip (Nothing :!: s')
291− Yield x s' -> Skip (Just x :!: s')
292− next (Just x :!: s) = case next0 s of
293− Done -> Done
294− Skip s' -> Skip (Just x :!: s')
295− Yield x' s' -> Yield x (Just x' :!: s')
296−{-# INLINE [0] init #-}
297−
298−-- | /O(1)/ Tests whether a Stream Char is empty or not.
299−null :: Stream Char -> Bool
300−null (Stream next s0 _len) = loop_null s0
301− where
302− loop_null !s = case next s of
303− Done -> True
304− Yield _ _ -> False
305− Skip s' -> loop_null s'
306−{-# INLINE[0] null #-}
307−
308−-- | /O(n)/ Returns the number of characters in a text.
309120length :: Stream Char -> Int
310−length (Stream next s0 _len) = loop_length 0# s0
311− where
312−
313− loop_length z# s = case next s of
314− Done -> (I# z#)
315− Skip s' -> loop_length z# s'
316− Yield _ s' -> loop_length (z# +# 1#) s'
121+length = S.lengthI
317122{-# INLINE[0] length #-}
318123
319−-- | /O(n)/ Returns the number of characters in a text.
320−length64 :: Stream Char -> Int64
321−length64 (Stream next s0 _len) = loop_length 0 s0
322− where
323− loop_length z s = case next s of
324− Done -> z
325− Skip s' -> loop_length z s'
326− Yield _ s' -> let !z' = z + 1
327− in loop_length z' s'
328−{-# INLINE[0] length64 #-}
329−
330−-- ----------------------------------------------------------------------------
331−-- * Stream transformations
332−
333−-- | /O(n)/ 'map' @f @xs is the Stream Char obtained by applying @f@ to each element of
334−-- @xs@.
335−map :: (Char -> Char) -> Stream Char -> Stream Char
336−map f (Stream next0 s0 len) = Stream next s0 len
337− where
338− {-# INLINE next #-}
339− next !s = case next0 s of
340− Done -> Done
341− Skip s' -> Skip s'
342− Yield x s' -> Yield (f x) s'
343−{-# INLINE [0] map #-}
344−
345−{-#
346− RULES "STREAM map/map fusion" forall f g s.
347− map f (map g s) = map (\x -> f (g x)) s
348− #-}
349−
350−-- | /O(n)/ Take a character and place it between each of the
351−-- characters of a 'Stream Char'.
352−intersperse :: Char -> Stream Char -> Stream Char
353−intersperse c (Stream next0 s0 len) = Stream next (s0 :!: Nothing :!: S1) len
354− where
355− {-# INLINE next #-}
356− next (s :!: Nothing :!: S1) = case next0 s of
357− Done -> Done
358− Skip s' -> Skip (s' :!: Nothing :!: S1)
359− Yield x s' -> Skip (s' :!: Just x :!: S1)
360− next (s :!: Just x :!: S1) = Yield x (s :!: Nothing :!: S2)
361− next (s :!: Nothing :!: S2) = case next0 s of
362− Done -> Done
363− Skip s' -> Skip (s' :!: Nothing :!: S2)
364− Yield x s' -> Yield c (s' :!: Just x :!: S1)
365− next _ = internalError "intersperse"
366−{-# INLINE [0] intersperse #-}
367−
368124-- | /O(n)/ Reverse the characters of a string.
369125reverse :: Stream Char -> Text
370126reverse (Stream next s len0)
@@ -400,181 +156,6 @@ reverse (Stream next s len0)
400156 loop t (j-2) l mar
401157{-# INLINE [0] reverse #-}
402158
403−-- ----------------------------------------------------------------------------
404−-- * Reducing Streams (folds)
405−
406−-- | foldl, applied to a binary operator, a starting value (typically the
407−-- left-identity of the operator), and a Stream, reduces the Stream using the
408−-- binary operator, from left to right.
409−foldl :: (b -> Char -> b) -> b -> Stream Char -> b
410−foldl f z0 (Stream next s0 _len) = loop_foldl z0 s0
411− where
412− loop_foldl z !s = case next s of
413− Done -> z
414− Skip s' -> loop_foldl z s'
415− Yield x s' -> loop_foldl (f z x) s'
416−{-# INLINE [0] foldl #-}
417−
418−-- | A strict version of foldl.
419−foldl' :: (b -> Char -> b) -> b -> Stream Char -> b
420−foldl' f z0 (Stream next s0 _len) = loop_foldl' z0 s0
421− where
422− loop_foldl' !z !s = case next s of
423− Done -> z
424− Skip s' -> loop_foldl' z s'
425− Yield x s' -> loop_foldl' (f z x) s'
426−{-# INLINE [0] foldl' #-}
427−
428−-- | foldl1 is a variant of foldl that has no starting value argument,
429−-- and thus must be applied to non-empty Streams.
430−foldl1 :: (Char -> Char -> Char) -> Stream Char -> Char
431−foldl1 f (Stream next s0 _len) = loop0_foldl1 s0
432− where
433− loop0_foldl1 !s = case next s of
434− Skip s' -> loop0_foldl1 s'
435− Yield x s' -> loop_foldl1 x s'
436− Done -> emptyError "foldl1"
437− loop_foldl1 z !s = case next s of
438− Done -> z
439− Skip s' -> loop_foldl1 z s'
440− Yield x s' -> loop_foldl1 (f z x) s'
441−{-# INLINE [0] foldl1 #-}
442−
443−-- | A strict version of foldl1.
444−foldl1' :: (Char -> Char -> Char) -> Stream Char -> Char
445−foldl1' f (Stream next s0 _len) = loop0_foldl1' s0
446− where
447− loop0_foldl1' !s = case next s of
448− Skip s' -> loop0_foldl1' s'
449− Yield x s' -> loop_foldl1' x s'
450− Done -> emptyError "foldl1"
451− loop_foldl1' !z !s = case next s of
452− Done -> z
453− Skip s' -> loop_foldl1' z s'
454− Yield x s' -> loop_foldl1' (f z x) s'
455−{-# INLINE [0] foldl1' #-}
456−
457−-- | 'foldr', applied to a binary operator, a starting value (typically the
458−-- right-identity of the operator), and a stream, reduces the stream using the
459−-- binary operator, from right to left.
460−foldr :: (Char -> b -> b) -> b -> Stream Char -> b
461−foldr f z (Stream next s0 _len) = loop_foldr s0
462− where
463− loop_foldr !s = case next s of
464− Done -> z
465− Skip s' -> loop_foldr s'
466− Yield x s' -> f x (loop_foldr s')
467−{-# INLINE [0] foldr #-}
468−
469−-- | foldr1 is a variant of 'foldr' that has no starting value argument,
470−-- and thus must be applied to non-empty streams.
471−-- Subject to array fusion.
472−foldr1 :: (Char -> Char -> Char) -> Stream Char -> Char
473−foldr1 f (Stream next s0 _len) = loop0_foldr1 s0
474− where
475− loop0_foldr1 !s = case next s of
476− Done -> emptyError "foldr1"
477− Skip s' -> loop0_foldr1 s'
478− Yield x s' -> loop_foldr1 x s'
479−
480− loop_foldr1 x !s = case next s of
481− Done -> x
482− Skip s' -> loop_foldr1 x s'
483− Yield x' s' -> f x (loop_foldr1 x' s')
484−{-# INLINE [0] foldr1 #-}
485−
486−intercalate :: Stream Char -> [Stream Char] -> Stream Char
487−intercalate s = concat . (L.intersperse s)
488−{-# INLINE [0] intercalate #-}
489−
490−-- ----------------------------------------------------------------------------
491−-- ** Special folds
492−
493−-- | /O(n)/ Concatenate a list of streams. Subject to array fusion.
494−concat :: [Stream Char] -> Stream Char
495−concat = L.foldr append (Stream next Done 0)
496− where
497− next Done = Done
498− next _ = internalError "concat"
499−
500−-- | Map a function over a stream that results in a stream and concatenate the
501−-- results.
502−concatMap :: (Char -> Stream Char) -> Stream Char -> Stream Char
503−concatMap f = foldr (append . f) empty
504−
505−-- | /O(n)/ any @p @xs determines if any character in the stream
506−-- @xs@ satisifes the predicate @p@.
507−any :: (Char -> Bool) -> Stream Char -> Bool
508−any p (Stream next0 s0 _len) = loop_any s0
509− where
510− loop_any !s = case next0 s of
511− Done -> False
512− Skip s' -> loop_any s'
513− Yield x s' | p x -> True
514− | otherwise -> loop_any s'
515−{-# INLINE [0] any #-}
516−
517−-- | /O(n)/ all @p @xs determines if all characters in the 'Text'
518−-- @xs@ satisify the predicate @p@.
519−all :: (Char -> Bool) -> Stream Char -> Bool
520−all p (Stream next0 s0 _len) = loop_all s0
521− where
522− loop_all !s = case next0 s of
523− Done -> True
524− Skip s' -> loop_all s'
525− Yield x s' | p x -> loop_all s'
526− | otherwise -> False
527−{-# INLINE [0] all #-}
528−
529−-- | /O(n)/ maximum returns the maximum value from a stream, which must be
530−-- non-empty.
531−maximum :: Stream Char -> Char
532−maximum (Stream next0 s0 _len) = loop0_maximum s0
533− where
534− loop0_maximum !s = case next0 s of
535− Done -> emptyError "maximum"
536− Skip s' -> loop0_maximum s'
537− Yield x s' -> loop_maximum x s'
538− loop_maximum !z !s = case next0 s of
539− Done -> z
540− Skip s' -> loop_maximum z s'
541− Yield x s'
542− | x > z -> loop_maximum x s'
543− | otherwise -> loop_maximum z s'
544−{-# INLINE [0] maximum #-}
545−
546−-- | /O(n)/ minimum returns the minimum value from a 'Text', which must be
547−-- non-empty.
548−minimum :: Stream Char -> Char
549−minimum (Stream next0 s0 _len) = loop0_minimum s0
550− where
551− loop0_minimum !s = case next0 s of
552− Done -> emptyError "minimum"
553− Skip s' -> loop0_minimum s'
554− Yield x s' -> loop_minimum x s'
555− loop_minimum !z !s = case next0 s of
556− Done -> z
557− Skip s' -> loop_minimum z s'
558− Yield x s'
559− | x < z -> loop_minimum x s'
560− | otherwise -> loop_minimum z s'
561−{-# INLINE [0] minimum #-}
562−
563−-- -----------------------------------------------------------------------------
564−-- * Building streams
565−
566−scanl :: (Char -> Char -> Char) -> Char -> Stream Char -> Stream Char
567−scanl f z0 (Stream next0 s0 len) = Stream next (S1 :!: z0 :!: s0) (len+1)
568− where
569− {-# INLINE next #-}
570− next (S1 :!: z :!: s) = Yield z (S2 :!: z :!: s)
571− next (S2 :!: z :!: s) = case next0 s of
572− Yield x s' -> let !x' = f z x
573− in Yield x' (S2 :!: x' :!: s')
574− Skip s' -> Skip (S2 :!: z :!: s')
575− Done -> Done
576−{-# INLINE [0] scanl #-}
577−
578159-- | /O(n)/ Perform the equivalent of 'scanr' over a list, only with
579160-- the input and result reversed.
580161reverseScanr :: (Char -> Char -> Char) -> Char -> Stream Char -> Stream Char
@@ -589,218 +170,14 @@ reverseScanr f z0 (Stream next0 s0 len) = Stream next (S1 :!: z0 :!: s0) (len+1)
589170 Done -> Done
590171{-# INLINE reverseScanr #-}
591172
592−-- -----------------------------------------------------------------------------
593−-- ** Accumulating maps
594−
595−-- | /O(n)/ Like a combination of 'map' and 'foldl'. Applies a
596−-- function to each element of a stream, passing an accumulating
597−-- parameter from left to right, and returns a final stream.
598−--
599−-- /Note/: Unlike the version over lists, this function does not
600−-- return a final value for the accumulator, because the nature of
601−-- streams precludes it.
602−mapAccumL :: (a -> b -> (a,b)) -> a -> Stream b -> Stream b
603−mapAccumL f z0 (Stream next0 s0 len) = Stream next (s0 :!: z0) len
604− where
605− {-# INLINE next #-}
606− next (s :!: z) = case next0 s of
607− Yield x s' -> let (z',y) = f z x
608− in Yield y (s' :!: z')
609− Skip s' -> Skip (s' :!: z)
610− Done -> Done
611−{-# INLINE [0] mapAccumL #-}
612−
613−-- -----------------------------------------------------------------------------
614−-- ** Generating and unfolding streams
615−
616−replicate :: Int -> Char -> Stream Char
617−replicate n c
618− | n < 0 = empty
619− | otherwise = Stream next 0 n
620− where
621− {-# INLINE next #-}
622− next i | i >= n = Done
623− | otherwise = Yield c (i + 1)
624−{-# INLINE [0] replicate #-}
625−
626−-- | /O(n)/, where @n@ is the length of the result. The unfoldr function
627−-- is analogous to the List 'unfoldr'. unfoldr builds a stream
628−-- from a seed value. The function takes the element and returns
629−-- Nothing if it is done producing the stream or returns Just
630−-- (a,b), in which case, a is the next Char in the string, and b is
631−-- the seed value for further production.
632−unfoldr :: (a -> Maybe (Char,a)) -> a -> Stream Char
633−unfoldr f s0 = Stream next s0 1
634− where
635− {-# INLINE next #-}
636− next !s = case f s of
637− Nothing -> Done
638− Just (w, s') -> Yield w s'
639−{-# INLINE [0] unfoldr #-}
640−
641−-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a stream from a seed
642−-- value. However, the length of the result is limited by the
643−-- first argument to 'unfoldrN'. This function is more efficient than
644−-- 'unfoldr' when the length of the result is known.
645−unfoldrI :: Integral a => a -> (b -> Maybe (Char,b)) -> b -> Stream Char
646−unfoldrI n f s0 | n < 0 = empty
647− | otherwise = Stream next (0 :!: s0) (fromIntegral (n*2))
648− where
649− {-# INLINE next #-}
650− next (z :!: s) = case f s of
651− Nothing -> Done
652− Just (w, s') | z >= n -> Done
653− | otherwise -> Yield w ((z + 1) :!: s')
654−{-# INLINE unfoldrI #-}
655−
656173-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a stream from a seed
657174-- value. However, the length of the result is limited by the
658175-- first argument to 'unfoldrN'. This function is more efficient than
659176-- 'unfoldr' when the length of the result is known.
660177unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Stream Char
661−unfoldrN n = unfoldrI (fromIntegral n :: Int)
178+unfoldrN n = S.unfoldrNI (fromIntegral n :: Int)
662179{-# INLINE [0] unfoldrN #-}
663180
664−-- | /O(n)/ Like 'unfoldr', 'unfoldrN64' builds a stream from a seed
665−-- value. However, the length of the result is limited by the
666−-- first argument to 'unfoldrN64'. This function is more efficient than
667−-- 'unfoldr' when the length of the result is known.
668−unfoldrN64 :: Int64 -> (a -> Maybe (Char,a)) -> a -> Stream Char
669−unfoldrN64 n = unfoldrI (fromIntegral n :: Int64)
670−{-# INLINE [0] unfoldrN64 #-}
671−
672−-------------------------------------------------------------------------------
673−-- * Substreams
674−
675−-- | /O(n)/ take n, applied to a stream, returns the prefix of the
676−-- stream of length @n@, or the stream itself if @n@ is greater than the
677−-- length of the stream.
678−take :: Int -> Stream Char -> Stream Char
679−take n0 (Stream next0 s0 len) = Stream next (n0 :!: s0) len
680− where
681− {-# INLINE next #-}
682− next (n :!: s) | n <= 0 = Done
683− | otherwise = case next0 s of
684− Done -> Done
685− Skip s' -> Skip (n :!: s')
686− Yield x s' -> Yield x ((n-1) :!: s')
687−{-# INLINE [0] take #-}
688−
689−-- | /O(n)/ drop n, applied to a stream, returns the suffix of the
690−-- stream of length @n@, or the empty stream if @n@ is greater than the
691−-- length of the stream.
692−drop :: Int -> Stream Char -> Stream Char
693−drop n0 (Stream next0 s0 len) = Stream next (Just ((max 0 n0)) :!: s0) (len - n0)
694− where
695− {-# INLINE next #-}
696− next (Just !n :!: s)
697− | n == 0 = Skip (Nothing :!: s)
698− | otherwise = case next0 s of
699− Done -> Done
700− Skip s' -> Skip (Just n :!: s')
701− Yield _ s' -> Skip (Just (n-1) :!: s')
702− next (Nothing :!: s) = case next0 s of
703− Done -> Done
704− Skip s' -> Skip (Nothing :!: s')
705− Yield x s' -> Yield x (Nothing :!: s')
706−{-# INLINE [0] drop #-}
707−
708−-- | takeWhile, applied to a predicate @p@ and a stream, returns the
709−-- longest prefix (possibly empty) of elements that satisfy p.
710−takeWhile :: (Char -> Bool) -> Stream Char -> Stream Char
711−takeWhile p (Stream next0 s0 len) = Stream next s0 len
712− where
713− {-# INLINE next #-}
714− next !s = case next0 s of
715− Done -> Done
716− Skip s' -> Skip s'
717− Yield x s' | p x -> Yield x s'
718− | otherwise -> Done
719−{-# INLINE [0] takeWhile #-}
720−
721−-- | dropWhile @p @xs returns the suffix remaining after takeWhile @p @xs.
722−dropWhile :: (Char -> Bool) -> Stream Char -> Stream Char
723−dropWhile p (Stream next0 s0 len) = Stream next (S1 :!: s0) len
724− where
725− {-# INLINE next #-}
726− next (S1 :!: s) = case next0 s of
727− Done -> Done
728− Skip s' -> Skip (S1 :!: s')
729− Yield x s' | p x -> Skip (S1 :!: s')
730− | otherwise -> Yield x (S2 :!: s')
731− next (S2 :!: s) = case next0 s of
732− Done -> Done
733− Skip s' -> Skip (S2 :!: s')
734− Yield x s' -> Yield x (S2 :!: s')
735−{-# INLINE [0] dropWhile #-}
736−
737−-- | /O(n)/ The 'isPrefixOf' function takes two 'Stream's and returns
738−-- 'True' iff the first is a prefix of the second.
739−isPrefixOf :: (Eq a) => Stream a -> Stream a -> Bool
740−isPrefixOf (Stream next1 s1 _) (Stream next2 s2 _) = loop (next1 s1) (next2 s2)
741− where
742− loop Done _ = True
743− loop _ Done = False
744− loop (Skip s1') (Skip s2') = loop (next1 s1') (next2 s2')
745− loop (Skip s1') x2 = loop (next1 s1') x2
746− loop x1 (Skip s2') = loop x1 (next2 s2')
747− loop (Yield x1 s1') (Yield x2 s2') = x1 == x2 &&
748− loop (next1 s1') (next2 s2')
749−{-# INLINE [0] isPrefixOf #-}
750−{-# SPECIALISE isPrefixOf :: Stream Char -> Stream Char -> Bool #-}
751−-- ----------------------------------------------------------------------------
752−-- * Searching
753−
754−-------------------------------------------------------------------------------
755−-- ** Searching by equality
756−
757−-- | /O(n)/ elem is the stream membership predicate.
758−elem :: Char -> Stream Char -> Bool
759−elem w (Stream next s0 _len) = loop_elem s0
760− where
761− loop_elem !s = case next s of
762− Done -> False
763− Skip s' -> loop_elem s'
764− Yield x s' | x == w -> True
765− | otherwise -> loop_elem s'
766−{-# INLINE [0] elem #-}
767−
768−-------------------------------------------------------------------------------
769−-- ** Searching with a predicate
770−
771−-- | /O(n)/ The 'find' function takes a predicate and a stream,
772−-- and returns the first element in matching the predicate, or 'Nothing'
773−-- if there is no such element.
774−
775−find :: (Char -> Bool) -> Stream Char -> Maybe Char
776−find p (Stream next s0 _len) = loop_find s0
777− where
778− loop_find !s = case next s of
779− Done -> Nothing
780− Skip s' -> loop_find s'
781− Yield x s' | p x -> Just x
782− | otherwise -> loop_find s'
783−{-# INLINE [0] find #-}
784−
785−-- | /O(n)/ 'filter', applied to a predicate and a stream,
786−-- returns a stream containing those characters that satisfy the
787−-- predicate.
788−filter :: (Char -> Bool) -> Stream Char -> Stream Char
789−filter p (Stream next0 s0 len) = Stream next s0 len
790− where
791− {-# INLINE next #-}
792− next !s = case next0 s of
793− Done -> Done
794− Skip s' -> Skip s'
795− Yield x s' | p x -> Yield x s'
796− | otherwise -> Skip s'
797−{-# INLINE [0] filter #-}
798−
799−{-# RULES
800− "Stream filter/filter fusion" forall p q s.
801− filter p (filter q s) = filter (\x -> q x && p x) s
802− #-}
803−
804181-------------------------------------------------------------------------------
805182-- ** Indexing streams
806183
@@ -885,22 +262,5 @@ count a (Stream next s0 _len) = loop 0 s0
885262 | otherwise -> loop i s'
886263{-# INLINE [0] count #-}
887264
888−-------------------------------------------------------------------------------
889−-- * Zipping
890−
891−-- | zipWith generalises 'zip' by zipping with the function given as
892−-- the first argument, instead of a tupling function.
893−zipWith :: (Char -> Char -> Char) -> Stream Char -> Stream Char -> Stream Char
894−zipWith f (Stream next0 sa0 len1) (Stream next1 sb0 len2) = Stream next (sa0 :!: sb0 :!: Nothing) (min len1 len2)
895− where
896− {-# INLINE next #-}
897− next (sa :!: sb :!: Nothing) = case next0 sa of
898− Done -> Done
899− Skip sa' -> Skip (sa' :!: sb :!: Nothing)
900− Yield a sa' -> Skip (sa' :!: sb :!: Just a)
901−
902− next (sa' :!: sb :!: Just a) = case next1 sb of
903− Done -> Done
904− Skip sb' -> Skip (sa' :!: sb' :!: Just a)
905− Yield b sb' -> Yield (f a b) (sa' :!: sb' :!: Nothing)
906−{-# INLINE [0] zipWith #-}
265+streamError :: String -> String -> a
266+streamError func msg = P.error $ "Data.Text.Fusion." ++ func ++ ": " ++ msg