@@ -140,6 +140,10 @@ module Data.Text
140140 , isSuffixOf
141141 , isInfixOf
142142
143+ -- ** View patterns
144+ , prefixed
145+ , suffixed
146+
143147 -- * Searching
144148 , filter
145149 , find
@@ -165,7 +169,7 @@ module Data.Text
165169import Prelude (Char, Bool(..), Functor(..), Int, Maybe(..), String,
166170 Eq(..), Ord(..), (++),
167171 Read(..), Show(..),
168− (&&), (||), (+), (-), (.), ($), (>>), (*),
172+ (&&), (||), (+), (-), (.), ($), ($!), (>>), (*),
169173 div, error, not, return, otherwise)
170174#if defined(HAVE_DEEPSEQ)
171175import Control.DeepSeq (NFData)
@@ -1289,5 +1293,52 @@ isInfixOf needle haystack
12891293 isInfixOf (singleton n) h = S.elem n (S.stream h)
12901294 #-}
12911295
1296+-------------------------------------------------------------------------------
1297+-- * View patterns
1298+
1299+-- | /O(n)/ Returns the suffix of the second string if its prefix
1300+-- matches the first.
1301+--
1302+-- Examples:
1303+--
1304+-- > prefixed "foo" "foobar" == Just "bar"
1305+-- > prefixed "foo" "quux" == Nothing
1306+--
1307+-- This is particularly useful with the @ViewPatterns@ extension to
1308+-- GHC, as follows:
1309+--
1310+-- > {-# LANGUAGE ViewPatterns #-}
1311+-- > import Data.Text as T
1312+-- >
1313+-- > fnordLength :: Text -> Int
1314+-- > fnordLength (prefixed "fnord" -> Just suf) = T.length suf
1315+-- > fnordLength _ = -1
1316+prefixed :: Text -> Text -> Maybe Text
1317+prefixed p@(Text _arr _off plen) t@(Text arr off len)
1318+ | p `isPrefixOf` t = Just $! textP arr (off+plen) (len-plen)
1319+ | otherwise = Nothing
1320+
1321+-- | /O(n)/ Returns the prefix of the second string if its suffix
1322+-- matches the first.
1323+--
1324+-- Examples:
1325+--
1326+-- > suffixed "bar" "foobar" == Just "foo"
1327+-- > suffixed "foo" "quux" == Nothing
1328+--
1329+-- This is particularly useful with the @ViewPatterns@ extension to
1330+-- GHC, as follows:
1331+--
1332+-- > {-# LANGUAGE ViewPatterns #-}
1333+-- > import Data.Text as T
1334+-- >
1335+-- > quuxLength :: Text -> Int
1336+-- > quuxLength (suffixed "quux" -> Just pre) = T.length pre
1337+-- > quuxLength _ = -1
1338+suffixed :: Text -> Text -> Maybe Text
1339+suffixed p@(Text _arr _off plen) t@(Text arr off len)
1340+ | p `isSuffixOf` t = Just $! textP arr off (len-plen)
1341+ | otherwise = Nothing
1342+
12921343emptyError :: String -> a
12931344emptyError fun = P.error ("Data.Text." ++ fun ++ ": empty input")