@@ -102,6 +102,7 @@ module Data.Text
102102 , drop
103103 , takeWhile
104104 , dropWhile
105+ , dropAfter
105106 , splitAt
106107 , span
107108 , break
@@ -172,7 +173,7 @@ import Data.Text.Fusion (stream, reverseStream, unstream)
172173
173174import Data.Text.Internal (Text(..), empty, text, textP)
174175import qualified Prelude as P
175−import Data.Text.Unsafe (iter, iter_, unsafeHead, unsafeTail)
176+import Data.Text.Unsafe (iter, iter_, reverseIter, unsafeHead, unsafeTail)
176177import Data.Text.UnsafeChar (unsafeChr)
177178import qualified Data.Text.Encoding.Utf16 as U16
178179
@@ -708,6 +709,24 @@ dropWhile p t@(Text arr off len) = loop 0 0
708709 unstream (S.dropWhile p (stream t)) = dropWhile p t
709710 #-}
710711
712+-- | /O(n)/ 'dropAfter' @p@ @t@ returns the prefix remaining after
713+-- dropping characters that fail the predicate @p@ from the end of
714+-- @t@. This function is subject to array fusion.
715+dropAfter :: (Char -> Bool) -> Text -> Text
716+dropAfter p t@(Text arr off len) = loop (len-1) len
717+ where loop !i !l | l <= 0 = empty
718+ | p c = loop (i+d) (l+d)
719+ | otherwise = Text arr off l
720+ where (c,d) = reverseIter t i
721+{-# INLINE [1] dropAfter #-}
722+
723+{-# RULES
724+"TEXT dropAfter -> fused" [~1] forall p t.
725+ dropAfter p t = S.reverse (S.dropWhile p (S.reverseStream t))
726+"TEXT dropAfter -> unfused" [1] forall p t.
727+ S.reverse (S.dropWhile p (S.reverseStream t)) = dropAfter p t
728+ #-}
729+
711730-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
712731-- prefix of @t@ of length @n@, and whose second is the remainder of
713732-- the string. It is equivalent to @('take' n t, 'drop' n t)@.