Bryan O'Sullivan avatar Bryan O'Sullivan committed 45634e0

Implement and test lazy break and span

Comments (0)

Files changed (2)

Data/Text/Lazy.hs

     , takeWhile
     , dropWhile
     , splitAt
-    -- , span
-    -- , break
+    , span
+    , break
     -- , group
     -- , groupBy
     -- , inits
                 Eq(..), Ord(..), (++),
                 Read(..), Show(..),
                 (&&), (||), (+), (-), (.), ($),
-                fromIntegral, not, return, otherwise)
+                flip, fromIntegral, not, return, otherwise)
 import qualified Prelude as P
 import Data.Int (Int64)
 import qualified Data.List as L
                            in (Chunk ts' Empty, Chunk ts'' Empty)
              | otherwise = let (ts',ts'') = loop (n - len) ts
                            in (Chunk t ts', ts'')
-             where len = T.length t
+             where len = fromIntegral (T.length t)
+
+-- | /O(n)/ 'break' is like 'span', but the prefix returned is over
+-- elements that fail the predicate @p@.
+break :: (Char -> Bool) -> Text -> (Text, Text)
+break p t0 = break' t0
+  where break' Empty          = (empty, empty)
+        break' c@(Chunk t ts) =
+          case T.findIndex p t of
+            Nothing      -> let (ts', ts'') = break' ts
+                            in (Chunk t ts', ts'')
+            Just n | n == 0    -> (Empty, c)
+                   | otherwise -> let (a,b) = T.splitAt n t
+                                  in (Chunk a Empty, Chunk b ts)
+
+-- | /O(n)/ 'span', applied to a predicate @p@ and text @t@, returns a
+-- pair whose first element is the longest prefix (possibly empty) of
+-- @t@ of elements that satisfy @p@, and whose second is the remainder
+-- of the list.
+span :: (Char -> Bool) -> Text -> (Text, Text)
+span p = break (not . p)
+{-# INLINE span #-}
+
+revChunks :: [T.Text] -> Text
+revChunks = L.foldl' (flip chunk) Empty
 
 emptyError :: String -> a
 emptyError fun = P.error ("Data.Text.Lazy." ++ fun ++ ": empty input")

tests/Properties.hs

 prop_T_splitAt n       = L.splitAt n   `eqP` (unpack2 . T.splitAt n)
 prop_TL_splitAt n      = L.splitAt n   `eqP` (unpack2 . TL.splitAt (fromIntegral n))
 prop_T_span p          = L.span p      `eqP` (unpack2 . T.span p)
+prop_TL_span p         = L.span p      `eqP` (unpack2 . TL.span p)
 prop_T_break p         = L.break p     `eqP` (unpack2 . T.break p)
+prop_TL_break p        = L.break p     `eqP` (unpack2 . TL.break p)
 prop_T_group           = L.group       `eqP` (map unpackT . T.group)
 prop_T_groupBy p       = L.groupBy p   `eqP` (map unpackT . T.groupBy p)
 prop_T_inits           = L.inits       `eqP` (map unpackT . T.inits)
   ("prop_TL_dropWhile", mytest prop_TL_dropWhile),
   ("prop_T_splitAt", mytest prop_T_splitAt),
   ("prop_T_span", mytest prop_T_span),
+  ("prop_TL_span", mytest prop_TL_span),
   ("prop_T_break", mytest prop_T_break),
+  ("prop_TL_break", mytest prop_TL_break),
   ("prop_T_group", mytest prop_T_group),
   ("prop_T_groupBy", mytest prop_T_groupBy),
   ("prop_T_inits", mytest prop_T_inits),
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.