@@ -22,77 +22,22 @@ module Data.Text.Fusion
23 -- * Creation and elimination
23 -- * Creation and elimination
26 , unstream
25 , unstream
28 , reverseStream
26 , reverseStream
44 -- * Transformations
30 -- * Transformations
66 -- * Construction
33 -- * Construction
67 -- ** Scans
34 -- ** Scans
69 , reverseScanr
35 , reverseScanr
71− -- ** Accumulating maps
74 -- ** Generation and unfolding
37 -- ** Generation and unfolding
77 , unfoldrN
38 , unfoldrN
81− -- ** Breaking strings
94 -- * Indexing
40 -- * Indexing
97 , findIndex
42 , findIndex
98 , findIndices
43 , findIndices
@@ -100,22 +45,17 @@ module Data.Text.Fusion
100 , elemIndex
45 , elemIndex
101 , elemIndices
46 , elemIndices
104− -- * Zipping and unzipping
108−import Prelude (Bool(..), Char, Either(..), Eq(..), Integral, Maybe(..),
50+import Prelude (Bool(..), Char, Eq(..), Maybe(..), Monad(..), Int,
109− Monad(..), Num(..), Ord(..), String, ($), (++), (.), (&&),
51+ Num(..), Ord(..), String, ($), (++), (&&),
110 fromIntegral, otherwise)
52 fromIntegral, otherwise)
111−import qualified Data.List as L
112−import GHC.Exts (Int(..), (+#))
113import Data.Bits ((.&.), shiftR)
53import Data.Bits ((.&.), shiftR)
114import Data.Char (ord)
54import Data.Char (ord)
115−import Data.Int (Int64)
116import Data.Text.Internal (Text(..))
55import Data.Text.Internal (Text(..))
117import Data.Text.UnsafeChar (unsafeChr, unsafeWrite)
56import Data.Text.UnsafeChar (unsafeChr, unsafeWrite)
118import qualified Data.Text.Array as A
57import qualified Data.Text.Array as A
58+import qualified Data.Text.Fusion.Common as S
119import Data.Text.Fusion.Internal
59import Data.Text.Fusion.Internal
120import qualified Data.Text.Internal as I
60import qualified Data.Text.Internal as I
121import qualified Data.Text.Encoding.Utf16 as U16
61import qualified Data.Text.Encoding.Utf16 as U16
@@ -173,198 +113,14 @@ unstream (Stream next0 s0 len)
173{-# INLINE [0] unstream #-}
113{-# INLINE [0] unstream #-}
174{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
114{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
176−streamError :: String -> String -> a
177−streamError func msg = P.error $ "Data.Text.Fusion." ++ func ++ ": " ++ msg
179−internalError :: String -> a
180−internalError func = streamError func "Internal error"
182−emptyError :: String -> a
183−emptyError func = internalError func "Empty input"
185-- ----------------------------------------------------------------------------
117-- ----------------------------------------------------------------------------
186-- * Basic stream functions
118-- * Basic stream functions
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)
193− next (S2 :!: s) = Yield w (S1 :!: s)
194− next (S1 :!: s) = case next0 s of
196− Skip s' -> Skip (S1 :!: s')
197− Yield x s' -> Yield x (S1 :!: s')
198−{-# INLINE [0] cons #-}
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)
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')
210−{-# INLINE [0] snoc #-}
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)
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
224− Skip s2' -> Skip (Right s2')
225− Yield x s2' -> Yield x (Right s2')
226−{-# INLINE [0] append #-}
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
233− loop_head !s = case next s of
235− Skip s' -> loop_head s'
236− Done -> streamError "head" "Empty stream"
237−{-# INLINE [0] head #-}
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
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'
248−{-# INLINE [0] uncons #-}
250−-- | /O(n)/ Returns the last character of a 'Stream Char', which must
252−last :: Stream Char -> Char
253−last (Stream next s0 _len) = loop0_last s0
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
261− Skip s' -> loop_last x s'
262− Yield x' s' -> loop_last x' s'
263−{-# INLINE[0] last #-}
265−-- | /O(1)/ Returns all characters after the head of a Stream Char, which must
267−tail :: Stream Char -> Stream Char
268−tail (Stream next0 s0 len) = Stream next (False :!: s0) (len-1)
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
277− Skip s' -> Skip (True :!: s')
278− Yield x s' -> Yield x (True :!: s')
279−{-# INLINE [0] tail #-}
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)
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
294− Skip s' -> Skip (Just x :!: s')
295− Yield x' s' -> Yield x (Just x' :!: s')
296−{-# INLINE [0] init #-}
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
302− loop_null !s = case next s of
305− Skip s' -> loop_null s'
306−{-# INLINE[0] null #-}
308−-- | /O(n)/ Returns the number of characters in a text.
309length :: Stream Char -> Int
120length :: Stream Char -> Int
310−length (Stream next s0 _len) = loop_length 0# s0
121+length = S.lengthI
313− loop_length z# s = case next s of
315− Skip s' -> loop_length z# s'
316− Yield _ s' -> loop_length (z# +# 1#) s'
317{-# INLINE[0] length #-}
122{-# INLINE[0] length #-}
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
323− loop_length z s = case next s of
325− Skip s' -> loop_length z s'
326− Yield _ s' -> let !z' = z + 1
327− in loop_length z' s'
328−{-# INLINE[0] length64 #-}
330−-- ----------------------------------------------------------------------------
331−-- * Stream transformations
333−-- | /O(n)/ 'map' @f @xs is the Stream Char obtained by applying @f@ to each element of
335−map :: (Char -> Char) -> Stream Char -> Stream Char
336−map f (Stream next0 s0 len) = Stream next s0 len
339− next !s = case next0 s of
342− Yield x s' -> Yield (f x) s'
343−{-# INLINE [0] map #-}
346− RULES "STREAM map/map fusion" forall f g s.
347− map f (map g s) = map (\x -> f (g x)) s
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
356− next (s :!: Nothing :!: S1) = case next0 s of
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
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 #-}
368-- | /O(n)/ Reverse the characters of a string.
124-- | /O(n)/ Reverse the characters of a string.
369reverse :: Stream Char -> Text
125reverse :: Stream Char -> Text
370reverse (Stream next s len0)
126reverse (Stream next s len0)
@@ -400,181 +156,6 @@ reverse (Stream next s len0)
400 loop t (j-2) l mar
156 loop t (j-2) l mar
401{-# INLINE [0] reverse #-}
157{-# INLINE [0] reverse #-}
403−-- ----------------------------------------------------------------------------
404−-- * Reducing Streams (folds)
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
412− loop_foldl z !s = case next s of
414− Skip s' -> loop_foldl z s'
415− Yield x s' -> loop_foldl (f z x) s'
416−{-# INLINE [0] foldl #-}
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
422− loop_foldl' !z !s = case next s of
424− Skip s' -> loop_foldl' z s'
425− Yield x s' -> loop_foldl' (f z x) s'
426−{-# INLINE [0] foldl' #-}
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
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
439− Skip s' -> loop_foldl1 z s'
440− Yield x s' -> loop_foldl1 (f z x) s'
441−{-# INLINE [0] foldl1 #-}
443−-- | A strict version of foldl1.
444−foldl1' :: (Char -> Char -> Char) -> Stream Char -> Char
445−foldl1' f (Stream next s0 _len) = loop0_foldl1' s0
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
453− Skip s' -> loop_foldl1' z s'
454− Yield x s' -> loop_foldl1' (f z x) s'
455−{-# INLINE [0] foldl1' #-}
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
463− loop_foldr !s = case next s of
465− Skip s' -> loop_foldr s'
466− Yield x s' -> f x (loop_foldr s')
467−{-# INLINE [0] foldr #-}
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
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'
480− loop_foldr1 x !s = case next s of
482− Skip s' -> loop_foldr1 x s'
483− Yield x' s' -> f x (loop_foldr1 x' s')
484−{-# INLINE [0] foldr1 #-}
486−intercalate :: Stream Char -> [Stream Char] -> Stream Char
487−intercalate s = concat . (L.intersperse s)
488−{-# INLINE [0] intercalate #-}
490−-- ----------------------------------------------------------------------------
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)
498− next _ = internalError "concat"
500−-- | Map a function over a stream that results in a stream and concatenate the
502−concatMap :: (Char -> Stream Char) -> Stream Char -> Stream Char
503−concatMap f = foldr (append . f) empty
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
510− loop_any !s = case next0 s of
512− Skip s' -> loop_any s'
513− Yield x s' | p x -> True
514− | otherwise -> loop_any s'
515−{-# INLINE [0] any #-}
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
522− loop_all !s = case next0 s of
524− Skip s' -> loop_all s'
525− Yield x s' | p x -> loop_all s'
526− | otherwise -> False
527−{-# INLINE [0] all #-}
529−-- | /O(n)/ maximum returns the maximum value from a stream, which must be
531−maximum :: Stream Char -> Char
532−maximum (Stream next0 s0 _len) = loop0_maximum s0
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
540− Skip s' -> loop_maximum z s'
542− | x > z -> loop_maximum x s'
543− | otherwise -> loop_maximum z s'
544−{-# INLINE [0] maximum #-}
546−-- | /O(n)/ minimum returns the minimum value from a 'Text', which must be
548−minimum :: Stream Char -> Char
549−minimum (Stream next0 s0 _len) = loop0_minimum s0
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
557− Skip s' -> loop_minimum z s'
559− | x < z -> loop_minimum x s'
560− | otherwise -> loop_minimum z s'
561−{-# INLINE [0] minimum #-}
563−-- -----------------------------------------------------------------------------
564−-- * Building streams
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)
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')
576−{-# INLINE [0] scanl #-}
578-- | /O(n)/ Perform the equivalent of 'scanr' over a list, only with
159-- | /O(n)/ Perform the equivalent of 'scanr' over a list, only with
579-- the input and result reversed.
160-- the input and result reversed.
580reverseScanr :: (Char -> Char -> Char) -> Char -> Stream Char -> Stream Char
161reverseScanr :: (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)
589 Done -> Done
170 Done -> Done
590{-# INLINE reverseScanr #-}
171{-# INLINE reverseScanr #-}
592−-- -----------------------------------------------------------------------------
593−-- ** Accumulating maps
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.
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
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)
611−{-# INLINE [0] mapAccumL #-}
613−-- -----------------------------------------------------------------------------
614−-- ** Generating and unfolding streams
616−replicate :: Int -> Char -> Stream Char
619− | otherwise = Stream next 0 n
622− next i | i >= n = Done
623− | otherwise = Yield c (i + 1)
624−{-# INLINE [0] replicate #-}
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
636− next !s = case f s of
638− Just (w, s') -> Yield w s'
639−{-# INLINE [0] unfoldr #-}
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))
650− next (z :!: s) = case f s of
652− Just (w, s') | z >= n -> Done
653− | otherwise -> Yield w ((z + 1) :!: s')
654−{-# INLINE unfoldrI #-}
656-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a stream from a seed
173-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a stream from a seed
657-- value. However, the length of the result is limited by the
174-- value. However, the length of the result is limited by the
658-- first argument to 'unfoldrN'. This function is more efficient than
175-- first argument to 'unfoldrN'. This function is more efficient than
659-- 'unfoldr' when the length of the result is known.
176-- 'unfoldr' when the length of the result is known.
660unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Stream Char
177unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Stream Char
661−unfoldrN n = unfoldrI (fromIntegral n :: Int)
178+unfoldrN n = S.unfoldrNI (fromIntegral n :: Int)
662{-# INLINE [0] unfoldrN #-}
179{-# INLINE [0] unfoldrN #-}
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 #-}
672−-------------------------------------------------------------------------------
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
682− next (n :!: s) | n <= 0 = Done
683− | otherwise = case next0 s of
685− Skip s' -> Skip (n :!: s')
686− Yield x s' -> Yield x ((n-1) :!: s')
687−{-# INLINE [0] take #-}
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)
696− next (Just !n :!: s)
697− | n == 0 = Skip (Nothing :!: s)
698− | otherwise = case next0 s of
700− Skip s' -> Skip (Just n :!: s')
701− Yield _ s' -> Skip (Just (n-1) :!: s')
702− next (Nothing :!: s) = case next0 s of
704− Skip s' -> Skip (Nothing :!: s')
705− Yield x s' -> Yield x (Nothing :!: s')
706−{-# INLINE [0] drop #-}
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
714− next !s = case next0 s of
717− Yield x s' | p x -> Yield x s'
719−{-# INLINE [0] takeWhile #-}
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
726− next (S1 :!: s) = case next0 s of
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
733− Skip s' -> Skip (S2 :!: s')
734− Yield x s' -> Yield x (S2 :!: s')
735−{-# INLINE [0] dropWhile #-}
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)
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−-- ----------------------------------------------------------------------------
754−-------------------------------------------------------------------------------
755−-- ** Searching by equality
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
761− loop_elem !s = case next s of
763− Skip s' -> loop_elem s'
764− Yield x s' | x == w -> True
765− | otherwise -> loop_elem s'
766−{-# INLINE [0] elem #-}
768−-------------------------------------------------------------------------------
769−-- ** Searching with a predicate
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.
775−find :: (Char -> Bool) -> Stream Char -> Maybe Char
776−find p (Stream next s0 _len) = loop_find s0
778− loop_find !s = case next s of
780− Skip s' -> loop_find s'
781− Yield x s' | p x -> Just x
782− | otherwise -> loop_find s'
783−{-# INLINE [0] find #-}
785−-- | /O(n)/ 'filter', applied to a predicate and a stream,
786−-- returns a stream containing those characters that satisfy the
788−filter :: (Char -> Bool) -> Stream Char -> Stream Char
789−filter p (Stream next0 s0 len) = Stream next s0 len
792− next !s = case next0 s of
795− Yield x s' | p x -> Yield x s'
796− | otherwise -> Skip s'
797−{-# INLINE [0] filter #-}
800− "Stream filter/filter fusion" forall p q s.
801− filter p (filter q s) = filter (\x -> q x && p x) s
804-------------------------------------------------------------------------------
181-------------------------------------------------------------------------------
805-- ** Indexing streams
182-- ** Indexing streams
@@ -885,22 +262,5 @@ count a (Stream next s0 _len) = loop 0 s0
885 | otherwise -> loop i s'
262 | otherwise -> loop i s'
886{-# INLINE [0] count #-}
263{-# INLINE [0] count #-}
888−-------------------------------------------------------------------------------
265+streamError :: String -> String -> a
889−-- * Zipping
266+streamError func msg = P.error $ "Data.Text.Fusion." ++ func ++ ": " ++ msg
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)
897− next (sa :!: sb :!: Nothing) = case next0 sa of
899− Skip sa' -> Skip (sa' :!: sb :!: Nothing)
900− Yield a sa' -> Skip (sa' :!: sb :!: Just a)
902− next (sa' :!: sb :!: Just a) = case next1 sb of
904− Skip sb' -> Skip (sa' :!: sb' :!: Just a)
905− Yield b sb' -> Yield (f a b) (sa' :!: sb' :!: Nothing)
906−{-# INLINE [0] zipWith #-}