Commits

Bryan O'Sullivan  committed dd7d50f

Implement and test lazy drop

  • Participants
  • Parent commits 0b09e9b

Comments (0)

Files changed (3)

File Data/Text/Fusion/Common.hs

 -- | /O(n)/ drop n, applied to a stream, returns the suffix of the
 -- stream of length @n@, or the empty stream if @n@ is greater than the
 -- length of the stream.
-drop :: Int -> Stream Char -> Stream Char
-drop n0 (Stream next0 s0 len) = Stream next (Just ((max 0 n0)) :!: s0) (len - n0)
+drop :: Integral a => a -> Stream Char -> Stream Char
+drop n0 (Stream next0 s0 len) =
+    Stream next (Just ((max 0 n0)) :!: s0) (len - fromIntegral n0)
   where
     {-# INLINE next #-}
     next (Just !n :!: s)

File Data/Text/Lazy.hs

 
     -- ** Breaking strings
     , take
-    -- , drop
+    , drop
     -- , takeWhile
     -- , dropWhile
     , splitAt
     unstream (S.take n (stream t)) = take n t
   #-}
 
+-- | /O(n)/ 'drop' @n@, applied to a 'Text', returns the suffix of the
+-- 'Text' of length @n@, or the empty 'Text' if @n@ is greater than the
+-- length of the 'Text'. Subject to fusion.
+drop :: Int -> Text -> Text
+drop i t0
+    | i <= 0 = t0
+    | otherwise = drop' i t0
+  where drop' 0 ts           = ts
+        drop' _ Empty        = Empty
+        drop' n (Chunk t ts) 
+            | n < len = Chunk (T.drop (fromIntegral n) t) ts
+            | otherwise = drop' (n - len) ts
+            where len = fromIntegral (T.length t)
+{-# INLINE [1] drop #-}
+
+{-# RULES
+"LAZY TEXT drop -> fused" [~1] forall n t.
+    drop n t = unstream (S.drop n (stream t))
+"LAZY TEXT drop -> unfused" [1] forall n t.
+    unstream (S.drop n (stream t)) = drop n t
+  #-}
+
 -- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
 -- prefix of @t@ of length @n@, and whose second is the remainder of
 -- the string. It is equivalent to @('take' n t, 'drop' n t)@.

File tests/Properties.hs

 prop_S_take n          = L.take n      `eqP` (unpackT . S.take n)
 prop_T_take n          = L.take n      `eqP` (unpackT . T.take n)
 prop_TL_take n         = L.take n      `eqP` (unpackT . TL.take (fromIntegral n))
+prop_S_drop n          = L.drop n      `eqP` (unpackT . S.drop n)
 prop_T_drop n          = L.drop n      `eqP` (unpackT . T.drop n)
+prop_TL_drop n         = L.drop n      `eqP` (unpackT . TL.drop n)
 prop_T_takeWhile p     = L.takeWhile p `eqP` (unpackT . T.takeWhile p)
 prop_T_takeWhileS p    = L.takeWhile p `eqP` (unpackT . S.unstream . S.takeWhile p . S.stream)
 prop_T_dropWhile p     = L.dropWhile p `eqP` (unpackT . T.dropWhile p)
   ("prop_S_take", mytest prop_S_take),
   ("prop_T_take", mytest prop_T_take),
   ("prop_TL_take", mytest prop_TL_take),
+  ("prop_S_drop", mytest prop_S_drop),
   ("prop_T_drop", mytest prop_T_drop),
+  ("prop_TL_drop", mytest prop_TL_drop),
   ("prop_T_takeWhile", mytest prop_T_takeWhile),
   ("prop_T_takeWhileS", mytest prop_T_takeWhileS),
   ("prop_T_dropWhile", mytest prop_T_dropWhile),