on master help sign in
Implement break and span

--HG-- extra : convert_revision : a7057ff1a4627333162b7133073b7d9ab4fefa14

commitb10927c9eac761d9958813b6c1f51f4fce5844bf authorBryan O'Sullivan <bos@serpentine.com> dateFri 6 Feb 2009, 21:18 (18 years ago) parent34f6990
2 files changed+32−7
Data/Text.hs+28−7 tests/Properties.hs+4
Data/Text.hs+28−7
@@ -96,8 +96,8 @@ module Data.Text
9696 , takeWhile
9797 , dropWhile
9898 , splitAt
99− -- , span
100− -- , break
99+ , span
100+ , break
101101 -- , group
102102 -- , groupBy
103103 , inits
@@ -148,7 +148,7 @@ import Prelude (Char, Bool, Functor(..), Int, Maybe(..), String,
148148 Show, showsPrec,
149149 Read, readsPrec,
150150 (&&), (||), (+), (-), (<), (>), (<=), (>=), (.),
151− return, otherwise)
151+ not, return, otherwise)
152152import Data.Char (isSpace)
153153import Control.Monad.ST (ST)
154154import qualified Data.Text.Array as A
@@ -634,7 +634,7 @@ dropWhile p (Text arr off len) = loop off 0
634634 #-}
635635
636636-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
637−-- prefix of @t@ of length @n@ and second element is the remainder of
637+-- prefix of @t@ of length @n@, and whose second is the remainder of
638638-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
639639splitAt :: Int -> Text -> (Text, Text)
640640splitAt n t@(Text arr off len)
@@ -644,11 +644,32 @@ splitAt n t@(Text arr off len)
644644 where k = loop off 0
645645 end = off + len
646646 loop !i !count
647− | i >= end || count >= n = i - off
648− | otherwise = loop (i+d) (count+1)
649− where d = iter_ arr i
647+ | i >= end || count >= n = i - off
648+ | otherwise = loop (i+d) (count+1)
649+ where d = iter_ arr i
650650{-# INLINE splitAt #-}
651651
652+-- | /O(n)/ 'span', applied to a predicate @p@ and text @t@, returns a
653+-- pair whose first element is the longest prefix (possibly empty) of
654+-- @t@ of elements that satisfy @p@, and whose second is the remainder
655+-- of the list.
656+span :: (Char -> Bool) -> Text -> (Text, Text)
657+span p t@(Text arr off len)
658+ | k == 0 = (empty, t)
659+ | k == len = (t, empty)
660+ | otherwise = (Text arr off k, Text arr (off+k) (len-k))
661+ where k = loop off 0
662+ loop !i !l | l >= len || not (p c) = l
663+ | otherwise = loop (i+d) (l+d)
664+ where (c,d) = iter arr i
665+{-# INLINE span #-}
666+
667+-- | /O(n)/ 'break' is like 'span', but the prefix returned is over
668+-- elements that fail the predicate @p@.
669+break :: (Char -> Bool) -> Text -> (Text, Text)
670+break p = span (not . p)
671+{-# INLINE break #-}
672+
652673-- | /O(n)/ Return all initial segments of the given 'Text', shortest
653674-- first.
654675inits :: Text -> [Text]
tests/Properties.hs+4
@@ -93,6 +93,8 @@ prop_takeWhileS p = L.takeWhile p `eqP` (unpack . unstream . S.takeWhile p .
9393prop_dropWhile p = L.dropWhile p `eqP` (unpack . T.dropWhile p)
9494prop_dropWhileS p = L.dropWhile p `eqP` (unpack . unstream . S.dropWhile p . stream)
9595prop_splitAt n = L.splitAt n `eqP` ((unpack *** unpack) . T.splitAt n)
96+prop_span p = L.span p `eqP` ((unpack *** unpack) . T.span p)
97+prop_break p = L.break p `eqP` ((unpack *** unpack) . T.break p)
9698prop_inits = L.inits `eqP` (map unpack . T.inits)
9799prop_tails = L.tails `eqP` (map unpack . T.tails)
98100
@@ -181,6 +183,8 @@ tests = [
181183 ("prop_dropWhile", mytest prop_dropWhile),
182184 ("prop_dropWhileS", mytest prop_dropWhileS),
183185 ("prop_splitAt", mytest prop_splitAt),
186+ ("prop_span", mytest prop_span),
187+ ("prop_break", mytest prop_break),
184188 ("prop_inits", mytest prop_inits),
185189 ("prop_tails", mytest prop_tails),
186190