on master help sign in
Implement and test lazy zipWith

--HG-- extra : convert_revision : 2f2a72e8ae4050ad54bd2e8df7c75a7812204862

commitd4acc5e00142d38c49469c7667617978c4b555c9 authorBryan O'Sullivan <bos@serpentine.com> dateSun 8 Mar 2009, 04:57 (18 years ago) parent27ac255
6 files changed+41−18
Data/Text.hs+2−1 Data/Text/Fusion.hs+3−14 Data/Text/Fusion/Common.hs+14 Data/Text/Lazy.hs+13−2 Data/Text/Lazy/Fusion.hs+6 tests/Properties.hs+3−1
Data/Text.hs+2−1
@@ -820,7 +820,7 @@ filter p t = unstream (S.filter p (stream t))
820820-------------------------------------------------------------------------------
821821-- ** Indexing 'Text's
822822
823−-- | /O(1)/ 'Text' index (subscript) operator, starting from 0.
823+-- | /O(n)/ 'Text' index (subscript) operator, starting from 0.
824824index :: Text -> Int -> Char
825825index t n = S.index (stream t) n
826826{-# INLINE index #-}
@@ -868,6 +868,7 @@ count c t = S.count c (stream t)
868868-- given as the first argument, instead of a tupling function.
869869zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text
870870zipWith f t1 t2 = unstream (S.zipWith f (stream t1) (stream t2))
871+{-# INLINE [0] zipWith #-}
871872
872873-- | /O(n)/ Breaks a 'Text' up into a list of words, delimited by 'Char's
873874-- representing white space.
Data/Text/Fusion.hs+3−14
@@ -48,7 +48,7 @@ module Data.Text.Fusion
4848 ) where
4949
5050import Prelude (Bool(..), Char, Eq(..), Maybe(..), Monad(..), Int,
51− Num(..), Ord(..), String, ($), (++), (&&),
51+ Num(..), Ord(..), ($), (&&),
5252 fromIntegral, otherwise)
5353import Data.Bits ((.&.), shiftR)
5454import Data.Char (ord)
@@ -181,17 +181,9 @@ unfoldrN n = S.unfoldrNI n
181181-------------------------------------------------------------------------------
182182-- ** Indexing streams
183183
184−-- | /O(1)/ stream index (subscript) operator, starting from 0.
184+-- | /O(n)/ stream index (subscript) operator, starting from 0.
185185index :: Stream Char -> Int -> Char
186−index (Stream next s0 _len) n0
187− | n0 < 0 = streamError "index" "Negative index"
188− | otherwise = loop_index n0 s0
189− where
190− loop_index !n !s = case next s of
191− Done -> streamError "index" "Index too large"
192− Skip s' -> loop_index n s'
193− Yield x s' | n == 0 -> x
194− | otherwise -> loop_index (n-1) s'
186+index = S.indexI
195187{-# INLINE [0] index #-}
196188
197189-- | The 'findIndex' function takes a predicate and a stream and
@@ -261,6 +253,3 @@ count a (Stream next s0 _len) = loop 0 s0
261253 Yield x s' | a == x -> loop (i+1) s'
262254 | otherwise -> loop i s'
263255{-# INLINE [0] count #-}
264−
265−streamError :: String -> String -> a
266−streamError func msg = P.error $ "Data.Text.Fusion." ++ func ++ ": " ++ msg
Data/Text/Fusion/Common.hs+14
@@ -79,6 +79,7 @@ module Data.Text.Fusion.Common
7979
8080 -- * Indexing
8181 , find
82+ , indexI
8283
8384 -- * Zipping and unzipping
8485 , zipWith
@@ -635,6 +636,19 @@ find p (Stream next s0 _len) = loop_find s0
635636 | otherwise -> loop_find s'
636637{-# INLINE [0] find #-}
637638
639+-- | /O(n)/ Stream index (subscript) operator, starting from 0.
640+indexI :: Integral a => Stream Char -> a -> Char
641+indexI (Stream next s0 _len) n0
642+ | n0 < 0 = streamError "index" "Negative index"
643+ | otherwise = loop_index n0 s0
644+ where
645+ loop_index !n !s = case next s of
646+ Done -> streamError "index" "Index too large"
647+ Skip s' -> loop_index n s'
648+ Yield x s' | n == 0 -> x
649+ | otherwise -> loop_index (n-1) s'
650+{-# INLINE [0] indexI #-}
651+
638652-- | /O(n)/ 'filter', applied to a predicate and a stream,
639653-- returns a stream containing those characters that satisfy the
640654-- predicate.
Data/Text/Lazy.hs+13−2
@@ -133,7 +133,7 @@ module Data.Text.Lazy
133133 -- , findSubstring
134134
135135 -- * Indexing
136− -- , index
136+ , index
137137 -- , findIndex
138138 -- , findIndices
139139 -- , elemIndex
@@ -141,7 +141,7 @@ module Data.Text.Lazy
141141 -- , count
142142
143143 -- * Zipping and unzipping
144− -- , zipWith
144+ , zipWith
145145
146146 -- -* Ordered text
147147 -- , sort
@@ -809,6 +809,17 @@ partition :: (Char -> Bool) -> Text -> (Text, Text)
809809partition p t = (filter p t, filter (not . p) t)
810810{-# INLINE partition #-}
811811
812+-- | /O(n)/ 'Text' index (subscript) operator, starting from 0.
813+index :: Text -> Int64 -> Char
814+index t n = S.index (stream t) n
815+{-# INLINE index #-}
816+
817+-- | /O(n)/ 'zipWith' generalises 'zip' by zipping with the function
818+-- given as the first argument, instead of a tupling function.
819+zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text
820+zipWith f t1 t2 = unstream (S.zipWith f (stream t1) (stream t2))
821+{-# INLINE [0] zipWith #-}
822+
812823revChunks :: [T.Text] -> Text
813824revChunks = L.foldl' (flip chunk) Empty
814825
Data/Text/Lazy/Fusion.hs+6
@@ -17,6 +17,7 @@ module Data.Text.Lazy.Fusion
1717 , unstreamChunks
1818 , length
1919 , unfoldrN
20+ , index
2021 ) where
2122
2223import Prelude hiding (length)
@@ -93,3 +94,8 @@ length = S.lengthI
9394unfoldrN :: Int64 -> (a -> Maybe (Char,a)) -> a -> Stream Char
9495unfoldrN n = S.unfoldrNI n
9596{-# INLINE [0] unfoldrN #-}
97+
98+-- | /O(n)/ stream index (subscript) operator, starting from 0.
99+index :: Stream Char -> Int64 -> Char
100+index = S.indexI
101+{-# INLINE [0] index #-}
tests/Properties.hs+3−1
@@ -318,13 +318,14 @@ prop_T_partition p = L.partition p `eqP` (unpack2 . T.partition p)
318318prop_TL_partition p = L.partition p `eqP` (unpack2 . TL.partition p)
319319
320320prop_T_index x s = x < L.length s && x >= 0 ==>
321− (L.!!) s x == T.index (packT s) x
321+ (L.!!) s x == T.index (packT s) x
322322prop_T_findIndex p = L.findIndex p `eqP` T.findIndex p
323323prop_T_findIndices p = L.findIndices p`eqP` T.findIndices p
324324prop_T_elemIndex c = L.elemIndex c `eqP` T.elemIndex c
325325prop_T_elemIndices c = L.elemIndices c`eqP` T.elemIndices c
326326prop_T_count c = (L.length . L.elemIndices c) `eqP` T.count c
327327prop_T_zipWith c s = L.zipWith c s `eqP` (unpackT . T.zipWith c (packT s))
328+prop_TL_zipWith c s = L.zipWith c s `eqP` (unpackT . TL.zipWith c (packT s))
328329
329330-- Regression tests.
330331prop_S_filter_eq s = S.filter p t == S.streamList (filter p s)
@@ -527,6 +528,7 @@ tests = [
527528 ("prop_T_elemIndices", mytest prop_T_elemIndices),
528529 ("prop_T_count", mytest prop_T_count),
529530 ("prop_T_zipWith", mytest prop_T_zipWith),
531+ ("prop_TL_zipWith", mytest prop_TL_zipWith),
530532
531533 ("prop_S_filter_eq", mytest prop_S_filter_eq)
532534 ]