on master help sign in
Implement break and span
b10927cBryan O'Sullivan
Data/Text.hs+28−7
@@ -96,8 +96,8 @@ module Data.Text
96 , takeWhile
96 , takeWhile
97 , dropWhile
97 , dropWhile
98 , splitAt
98 , splitAt
99− -- , span
99+ , span
100− -- , break
100+ , break
101 -- , group
101 -- , group
102 -- , groupBy
102 -- , groupBy
103 , inits
103 , inits
@@ -148,7 +148,7 @@ import Prelude (Char, Bool, Functor(..), Int, Maybe(..), String,
148 Show, showsPrec,
148 Show, showsPrec,
149 Read, readsPrec,
149 Read, readsPrec,
150 (&&), (||), (+), (-), (<), (>), (<=), (>=), (.),
150 (&&), (||), (+), (-), (<), (>), (<=), (>=), (.),
151− return, otherwise)
151+ not, return, otherwise)
152import Data.Char (isSpace)
152import Data.Char (isSpace)
153import Control.Monad.ST (ST)
153import Control.Monad.ST (ST)
154import qualified Data.Text.Array as A
154import qualified Data.Text.Array as A
@@ -634,7 +634,7 @@ dropWhile p (Text arr off len) = loop off 0
634 #-}
634 #-}
635
635
636-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
636-- | /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
638-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
638-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
639splitAt :: Int -> Text -> (Text, Text)
639splitAt :: Int -> Text -> (Text, Text)
640splitAt n t@(Text arr off len)
640splitAt n t@(Text arr off len)
@@ -644,11 +644,32 @@ splitAt n t@(Text arr off len)
644 where k = loop off 0
644 where k = loop off 0
645 end = off + len
645 end = off + len
646 loop !i !count
646 loop !i !count
647− | i >= end || count >= n = i - off
647+ | i >= end || count >= n = i - off
648− | otherwise = loop (i+d) (count+1)
648+ | otherwise = loop (i+d) (count+1)
649− where d = iter_ arr i
649+ where d = iter_ arr i
650{-# INLINE splitAt #-}
650{-# INLINE splitAt #-}
651
651
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+
652-- | /O(n)/ Return all initial segments of the given 'Text', shortest
673-- | /O(n)/ Return all initial segments of the given 'Text', shortest
653-- first.
674-- first.
654inits :: Text -> [Text]
675inits :: Text -> [Text]
tests/Properties.hs+4
@@ -93,6 +93,8 @@ prop_takeWhileS p = L.takeWhile p `eqP` (unpack . unstream . S.takeWhile p .
93prop_dropWhile p = L.dropWhile p `eqP` (unpack . T.dropWhile p)
93prop_dropWhile p = L.dropWhile p `eqP` (unpack . T.dropWhile p)
94prop_dropWhileS p = L.dropWhile p `eqP` (unpack . unstream . S.dropWhile p . stream)
94prop_dropWhileS p = L.dropWhile p `eqP` (unpack . unstream . S.dropWhile p . stream)
95prop_splitAt n = L.splitAt n `eqP` ((unpack *** unpack) . T.splitAt n)
95prop_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)
96prop_inits = L.inits `eqP` (map unpack . T.inits)
98prop_inits = L.inits `eqP` (map unpack . T.inits)
97prop_tails = L.tails `eqP` (map unpack . T.tails)
99prop_tails = L.tails `eqP` (map unpack . T.tails)
98
100
@@ -181,6 +183,8 @@ tests = [
181 ("prop_dropWhile", mytest prop_dropWhile),
183 ("prop_dropWhile", mytest prop_dropWhile),
182 ("prop_dropWhileS", mytest prop_dropWhileS),
184 ("prop_dropWhileS", mytest prop_dropWhileS),
183 ("prop_splitAt", mytest prop_splitAt),
185 ("prop_splitAt", mytest prop_splitAt),
186+ ("prop_span", mytest prop_span),
187+ ("prop_break", mytest prop_break),
184 ("prop_inits", mytest prop_inits),
188 ("prop_inits", mytest prop_inits),
185 ("prop_tails", mytest prop_tails),
189 ("prop_tails", mytest prop_tails),
186
190