on master help sign in
Implement and test lazy take
73f9b61Bryan O'Sullivan
Data/Text/Fusion/Common.hs+1−1
@@ -530,7 +530,7 @@ unfoldrNI n f s0 | n < 0 = empty
530-- | /O(n)/ take n, applied to a stream, returns the prefix of the
530-- | /O(n)/ take n, applied to a stream, returns the prefix of the
531-- stream of length @n@, or the stream itself if @n@ is greater than the
531-- stream of length @n@, or the stream itself if @n@ is greater than the
532-- length of the stream.
532-- length of the stream.
533−take :: Int -> Stream Char -> Stream Char
533+take :: Integral a => a -> Stream Char -> Stream Char
534take n0 (Stream next0 s0 len) = Stream next (n0 :!: s0) len
534take n0 (Stream next0 s0 len) = Stream next (n0 :!: s0) len
535 where
535 where
536 {-# INLINE next #-}
536 {-# INLINE next #-}
Data/Text/Lazy.hs+22−1
@@ -94,7 +94,7 @@ module Data.Text.Lazy
94 -- * Substrings
94 -- * Substrings
95
95
96 -- ** Breaking strings
96 -- ** Breaking strings
97− -- , take
97+ , take
98 -- , drop
98 -- , drop
99 -- , takeWhile
99 -- , takeWhile
100 -- , dropWhile
100 -- , dropWhile
@@ -493,6 +493,27 @@ unfoldrN :: Int64 -> (a -> Maybe (Char,a)) -> a -> Text
493unfoldrN n f s = unstream (S.unfoldrN n f s)
493unfoldrN n f s = unstream (S.unfoldrN n f s)
494{-# INLINE unfoldrN #-}
494{-# INLINE unfoldrN #-}
495
495
496+-- | /O(n)/ 'take' @n@, applied to a 'Text', returns the prefix of the
497+-- 'Text' of length @n@, or the 'Text' itself if @n@ is greater than
498+-- the length of the Text. Subject to fusion.
499+take :: Int64 -> Text -> Text
500+take i _ | i <= 0 = Empty
501+take i t0 = take' i t0
502+ where take' 0 _ = Empty
503+ take' _ Empty = Empty
504+ take' n (Chunk t ts)
505+ | n < len = Chunk (T.take (fromIntegral n) t) Empty
506+ | otherwise = Chunk t (take' (n - len) ts)
507+ where len = fromIntegral (T.length t)
508+{-# INLINE [1] take #-}
509+
510+{-# RULES
511+"LAZY TEXT take -> fused" [~1] forall n t.
512+ take n t = unstream (S.take n (stream t))
513+"LAZY TEXT take -> unfused" [1] forall n t.
514+ unstream (S.take n (stream t)) = take n t
515+ #-}
516+
496-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
517-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
497-- prefix of @t@ of length @n@, and whose second is the remainder of
518-- prefix of @t@ of length @n@, and whose second is the remainder of
498-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
519-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
tests/Properties.hs+4
@@ -215,7 +215,9 @@ prop_TL_unfoldrN n m = (L.take n . L.unfoldr (unf m)) `eq`
215unpack2 :: (Target t) => (t,t) -> (String,String)
215unpack2 :: (Target t) => (t,t) -> (String,String)
216unpack2 = unpackT *** unpackT
216unpack2 = unpackT *** unpackT
217
217
218+prop_S_take n = L.take n `eqP` (unpackT . S.take n)
218prop_T_take n = L.take n `eqP` (unpackT . T.take n)
219prop_T_take n = L.take n `eqP` (unpackT . T.take n)
220+prop_TL_take n = L.take n `eqP` (unpackT . TL.take (fromIntegral n))
219prop_T_drop n = L.drop n `eqP` (unpackT . T.drop n)
221prop_T_drop n = L.drop n `eqP` (unpackT . T.drop n)
220prop_T_takeWhile p = L.takeWhile p `eqP` (unpackT . T.takeWhile p)
222prop_T_takeWhile p = L.takeWhile p `eqP` (unpackT . T.takeWhile p)
221prop_T_takeWhileS p = L.takeWhile p `eqP` (unpackT . S.unstream . S.takeWhile p . S.stream)
223prop_T_takeWhileS p = L.takeWhile p `eqP` (unpackT . S.unstream . S.takeWhile p . S.stream)
@@ -408,7 +410,9 @@ tests = [
408 ("prop_T_unfoldrN", mytest prop_T_unfoldrN),
410 ("prop_T_unfoldrN", mytest prop_T_unfoldrN),
409 ("prop_TL_unfoldrN", mytest prop_TL_unfoldrN),
411 ("prop_TL_unfoldrN", mytest prop_TL_unfoldrN),
410
412
413+ ("prop_S_take", mytest prop_S_take),
411 ("prop_T_take", mytest prop_T_take),
414 ("prop_T_take", mytest prop_T_take),
415+ ("prop_TL_take", mytest prop_TL_take),
412 ("prop_T_drop", mytest prop_T_drop),
416 ("prop_T_drop", mytest prop_T_drop),
413 ("prop_T_takeWhile", mytest prop_T_takeWhile),
417 ("prop_T_takeWhile", mytest prop_T_takeWhile),
414 ("prop_T_takeWhileS", mytest prop_T_takeWhileS),
418 ("prop_T_takeWhileS", mytest prop_T_takeWhileS),