@@ -1053,30 +1053,46 @@ transpose ts = P.map pack (L.transpose (P.map unpack ts))
10531053-- (typically the left-identity of the operator), and a 'Text',
10541054-- reduces the 'Text' using the binary operator, from left to right.
10551055foldl :: (a -> Char -> a ) -> a -> Text -> a
1056- foldl f z t = S. foldl f z (stream t)
1056+ foldl f z (Text arr off len) = go (off + len - 1 )
1057+ where
1058+ go ! i
1059+ | i < off = z
1060+ | otherwise = let ! (Iter c l) = reverseIterArray arr i in f (go (i + l)) c
10571061{-# INLINE foldl #-}
10581062
10591063-- | /O(n)/ A strict version of 'foldl'.
10601064foldl' :: (a -> Char -> a ) -> a -> Text -> a
1061- foldl' f z t = S. foldl' f z (stream t)
1065+ foldl' f z (Text arr off len) = go off z
1066+ where
1067+ go ! i ! acc
1068+ | i >= off + len = acc
1069+ | otherwise = let ! (Iter c l) = iterArray arr i in go (i + l) (f acc c)
10621070{-# INLINE foldl' #-}
10631071
10641072-- | /O(n)/ A variant of 'foldl' that has no starting value argument,
10651073-- and thus must be applied to a non-empty 'Text'.
10661074foldl1 :: HasCallStack => (Char -> Char -> Char ) -> Text -> Char
1067- foldl1 f t = S. foldl1 f (stream t)
1075+ foldl1 f t = case uncons t of
1076+ Nothing -> emptyError " foldl"
1077+ Just (c, t') -> foldl f c t'
10681078{-# INLINE foldl1 #-}
10691079
10701080-- | /O(n)/ A strict version of 'foldl1'.
10711081foldl1' :: HasCallStack => (Char -> Char -> Char ) -> Text -> Char
1072- foldl1' f t = S. foldl1' f (stream t)
1082+ foldl1' f t = case uncons t of
1083+ Nothing -> emptyError " foldl'"
1084+ Just (c, t') -> foldl' f c t'
10731085{-# INLINE foldl1' #-}
10741086
10751087-- | /O(n)/ A monadic version of 'foldl''.
10761088--
10771089-- @since 2.1.2
10781090foldlM' :: Monad m => (a -> Char -> m a ) -> a -> Text -> m a
1079- foldlM' f z t = S. foldlM' f z (stream t)
1091+ foldlM' f z (Text arr off len) = go off z
1092+ where
1093+ go ! i ! acc
1094+ | i >= off + len = pure acc
1095+ | otherwise = let ! (Iter c l) = iterArray arr i in go (i + l) P. =<< f acc c
10801096{-# INLINE foldlM' #-}
10811097
10821098-- | /O(n)/ 'foldr', applied to a binary operator, a starting value
@@ -1099,13 +1115,19 @@ foldlM' f z t = S.foldlM' f z (stream t)
10991115-- Searches from left to right with short-circuiting behavior can
11001116-- also be defined using 'foldr' (/e.g./, 'any', 'all', 'find', 'elem').
11011117foldr :: (Char -> a -> a ) -> a -> Text -> a
1102- foldr f z t = S. foldr f z (stream t)
1118+ foldr f z (Text arr off len) = go off
1119+ where
1120+ go ! i
1121+ | i >= off + len = z
1122+ | otherwise = let ! (Iter c l) = iterArray arr i in f c (go (i + l))
11031123{-# INLINE foldr #-}
11041124
11051125-- | /O(n)/ A variant of 'foldr' that has no starting value argument,
11061126-- and thus must be applied to a non-empty 'Text'.
11071127foldr1 :: HasCallStack => (Char -> Char -> Char ) -> Text -> Char
1108- foldr1 f t = S. foldr1 f (stream t)
1128+ foldr1 f t = case unsnoc t of
1129+ Nothing -> emptyError " foldr1"
1130+ Just (t', c) -> foldr f c t'
11091131{-# INLINE foldr1 #-}
11101132
11111133-- | /O(n)/ A strict version of 'foldr'.
@@ -1114,7 +1136,11 @@ foldr1 f t = S.foldr1 f (stream t)
11141136--
11151137-- @since 2.0.1
11161138foldr' :: (Char -> a -> a ) -> a -> Text -> a
1117- foldr' f z t = S. foldl' (P. flip f) z (reverseStream t)
1139+ foldr' f z (Text arr off len) = go (off + len - 1 ) z
1140+ where
1141+ go ! i ! acc
1142+ | i < off = acc
1143+ | otherwise = let ! (Iter c l) = reverseIterArray arr i in go (i + l) (f c acc)
11181144{-# INLINE foldr' #-}
11191145
11201146-- -----------------------------------------------------------------------------
@@ -1144,25 +1170,30 @@ concatMap f = concat . foldr ((:) . f) []
11441170-- | /O(n)/ 'any' @p@ @t@ determines whether any character in the
11451171-- 'Text' @t@ satisfies the predicate @p@.
11461172any :: (Char -> Bool ) -> Text -> Bool
1147- any p t = S. any p (stream t)
1173+ any p = foldr ( \ c acc -> p c || acc) False
11481174{-# INLINE any #-}
11491175
11501176-- | /O(n)/ 'all' @p@ @t@ determines whether all characters in the
11511177-- 'Text' @t@ satisfy the predicate @p@.
11521178all :: (Char -> Bool ) -> Text -> Bool
1153- all p t = S. all p (stream t)
1179+ all p = foldr ( \ c acc -> p c && acc) True
11541180{-# INLINE all #-}
11551181
11561182-- | /O(n)/ 'maximum' returns the maximum value from a 'Text', which
11571183-- must be non-empty.
11581184maximum :: HasCallStack => Text -> Char
1159- maximum t = S. maximum (stream t)
1185+ maximum = foldl1' max
1186+ -- This could be implemented faster: look for the longest
1187+ -- and largest UTF-8 sequence, then decode it to Char only once,
1188+ -- instead of decoding all characters, but I doubt anyone cares
1189+ -- about the performance of 'maximum' much.
11601190{-# INLINE maximum #-}
11611191
11621192-- | /O(n)/ 'minimum' returns the minimum value from a 'Text', which
11631193-- must be non-empty.
11641194minimum :: HasCallStack => Text -> Char
1165- minimum t = S. minimum (stream t)
1195+ minimum = foldl1' min
1196+ -- This could be implemented faster, see the comment for 'maximum' above.
11661197{-# INLINE minimum #-}
11671198
11681199-- -----------------------------------------------------------------------------
@@ -1735,14 +1766,16 @@ chunksOf k = go
17351766-- returns 'True' if the element is found in the given 'Text', or
17361767-- 'False' otherwise.
17371768elem :: Char -> Text -> Bool
1738- elem c t = S. any (== c) (stream t)
1769+ elem = any . (==)
1770+ -- TODO This can be implemented much faster: there is no need to decode
1771+ -- any UTF-8 sequences at all.
17391772{-# INLINE elem #-}
17401773
17411774-- | /O(n)/ The 'find' function takes a predicate and a 'Text', and
17421775-- returns the first element matching the predicate, or 'Nothing' if
17431776-- there is no such element.
17441777find :: (Char -> Bool ) -> Text -> Maybe Char
1745- find p t = S. findBy p (stream t)
1778+ find p = foldr ( \ c acc -> if p c then Just c else acc) Nothing
17461779{-# INLINE find #-}
17471780
17481781-- | /O(n)/ The 'partition' function takes a predicate and a 'Text',
@@ -1903,7 +1936,7 @@ count pat
19031936-- | /O(n)/ The 'countChar' function returns the number of times the
19041937-- query element appears in the given 'Text'.
19051938countChar :: Char -> Text -> Int
1906- countChar c t = S. countChar c (stream t)
1939+ countChar c = foldl' ( \ acc c' -> if c == c' then acc + 1 else acc) 0
19071940{-# INLINE countChar #-}
19081941
19091942-------------------------------------------------------------------------------
0 commit comments