@@ -34,6 +34,7 @@
3434-- with Unicode text (including normalization, regular expressions,
3535-- non-standard encodings, text breaking, and locales), see
3636-- <http://hackage.haskell.org/package/text-icu the text-icu package >.
37+--
3738
3839module Data.Text
3940 (
@@ -43,6 +44,9 @@ module Data.Text
4344 -- * Acceptable data
4445 -- $replacement
4546
47+ -- * Definition of character
48+ -- $character_definition
49+
4650 -- * Fusion
4751 -- $fusion
4852
@@ -60,6 +64,7 @@ module Data.Text
6064 , snoc
6165 , append
6266 , uncons
67+ , unsnoc
6368 , head
6469 , last
6570 , tail
@@ -246,6 +251,18 @@ import qualified GHC.Exts as Exts
246251import Text.Printf (PrintfArg, formatArg, formatString)
247252#endif
248253
254+-- $character_definition
255+--
256+-- This package uses the term /character/ to denote Unicode /code points/.
257+--
258+-- Note that this is not the same thing as a grapheme (e.g. a
259+-- composition of code points that form one visual symbol). For
260+-- instance, consider the grapheme \"ä\". This symbol has two
261+-- Unicode representations: a single code-point representation
262+-- @U+00E4@ (the @LATIN SMALL LETTER A WITH DIAERESIS@ code point),
263+-- and a two code point representation @U+0061@ (the \"@A@\" code
264+-- point) and @U+0308@ (the @COMBINING DIAERESIS@ code point).
265+
249266-- $strict
250267--
251268-- This package provides both strict and lazy 'Text' types. The
@@ -334,9 +351,13 @@ instance Read Text where
334351 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
335352
336353#if MIN_VERSION_base(4,9,0)
337−-- Semigroup orphan instances for older GHCs are provided by
338−-- 'semigroups` package
339−
354+-- | Non-orphan 'Semigroup' instance only defined for
355+-- @base-4.9.0.0@ and later; orphan instances for older GHCs are
356+-- provided by
357+-- the [semigroups](http://hackage.haskell.org/package/semigroups)
358+-- package
359+--
360+-- @since 1.2.2.0
340361instance Semigroup Text where
341362 (<>) = append
342363#endif
@@ -354,6 +375,7 @@ instance IsString Text where
354375 fromString = pack
355376
356377#if __GLASGOW_HASKELL__ >= 708
378+-- | @since 1.2.0.0
357379instance Exts.IsList Text where
358380 type Item Text = Char
359381 fromList = pack
@@ -364,6 +386,7 @@ instance Exts.IsList Text where
364386instance NFData Text where rnf !_ = ()
365387#endif
366388
389+-- | @since 1.2.1.0
367390instance Binary Text where
368391 put t = put (encodeUtf8 t)
369392 get = do
@@ -397,6 +420,8 @@ instance Data Text where
397420
398421#if MIN_VERSION_base(4,7,0)
399422-- | Only defined for @base-4.7.0.0@ and later
423+--
424+-- @since 1.2.2.0
400425instance PrintfArg Text where
401426 formatArg txt = formatString $ unpack txt
402427#endif
@@ -545,6 +570,19 @@ init (Text arr off len) | len <= 0 = emptyError "init"
545570 unstream (S.init (stream t)) = init t
546571 #-}
547572
573+-- | /O(1)/ Returns all but the last character and the last character of a
574+-- 'Text', or 'Nothing' if empty.
575+--
576+-- @since 1.2.3.0
577+unsnoc :: Text -> Maybe (Text, Char)
578+unsnoc (Text arr off len)
579+ | len <= 0 = Nothing
580+ | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
581+ | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
582+ where n = A.unsafeIndex arr (off+len-1)
583+ n0 = A.unsafeIndex arr (off+len-2)
584+{-# INLINE [1] unsnoc #-}
585+
548586-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
549587-- fusion.
550588null :: Text -> Bool
@@ -624,8 +662,15 @@ compareLength t n = S.compareLengthI (stream t) n
624662-- -----------------------------------------------------------------------------
625663-- * Transformations
626664-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
627−-- each element of @t@. Subject to fusion. Performs replacement on
628−-- invalid scalar values.
665+-- each element of @t@.
666+--
667+-- Example:
668+--
669+-- >>> let message = pack "I am not angry. Not at all."
670+-- >>> T.map (\c -> if c == '.' then '!' else c) message
671+-- "I am not angry! Not at all!"
672+--
673+-- Subject to fusion. Performs replacement on invalid scalar values.
629674map :: (Char -> Char) -> Text -> Text
630675map f t = unstream (S.map (safe . f) (stream t))
631676{-# INLINE [1] map #-}
@@ -633,18 +678,36 @@ map f t = unstream (S.map (safe . f) (stream t))
633678-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
634679-- 'Text's and concatenates the list after interspersing the first
635680-- argument between each element of the list.
681+--
682+-- Example:
683+--
684+-- >>> T.intercalate "NI!" ["We", "seek", "the", "Holy", "Grail"]
685+-- "WeNI!seekNI!theNI!HolyNI!Grail"
636686intercalate :: Text -> [Text] -> Text
637687intercalate t = concat . (F.intersperse t)
638688{-# INLINE intercalate #-}
639689
640690-- | /O(n)/ The 'intersperse' function takes a character and places it
641−-- between the characters of a 'Text'. Subject to fusion. Performs
642−-- replacement on invalid scalar values.
691+-- between the characters of a 'Text'.
692+--
693+-- Example:
694+--
695+-- >>> T.intersperse '.' "SHIELD"
696+-- "S.H.I.E.L.D"
697+--
698+-- Subject to fusion. Performs replacement on invalid scalar values.
643699intersperse :: Char -> Text -> Text
644700intersperse c t = unstream (S.intersperse (safe c) (stream t))
645701{-# INLINE intersperse #-}
646702
647−-- | /O(n)/ Reverse the characters of a string. Subject to fusion.
703+-- | /O(n)/ Reverse the characters of a string.
704+--
705+-- Example:
706+--
707+-- >>> T.reverse "desrever"
708+-- "reversed"
709+--
710+-- Subject to fusion.
648711reverse :: Text -> Text
649712reverse t = S.reverse (stream t)
650713{-# INLINE reverse #-}
@@ -663,12 +726,14 @@ reverse t = S.reverse (stream t)
663726-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
664727-- be replaced recursively:
665728--
666−-- > replace "oo" "foo" "oo" == "foo"
729+-- >>> replace "oo" "foo" "oo"
730+-- "foo"
667731--
668732-- In cases where several instances of @needle@ overlap, only the
669733-- first one will be replaced:
670734--
671−-- > replace "ofo" "bar" "ofofo" == "barfo"
735+-- >>> replace "ofo" "bar" "ofofo"
736+-- "barfo"
672737--
673738-- In (unlikely) bad cases, this function's time complexity degrades
674739-- towards /O(n*m)/.
@@ -782,6 +847,8 @@ toUpper t = unstream (S.toUpper (stream t))
782847-- guides disagree on whether the book name \"The Hill of the Red
783848-- Fox\" is correctly title cased—but this function will
784849-- capitalize /every/ word.
850+--
851+-- @since 1.0.0.0
785852toTitle :: Text -> Text
786853toTitle t = unstream (S.toTitle (stream t))
787854{-# INLINE toTitle #-}
@@ -792,8 +859,11 @@ toTitle t = unstream (S.toTitle (stream t))
792859--
793860-- Examples:
794861--
795−-- > justifyLeft 7 'x' "foo" == "fooxxxx"
796−-- > justifyLeft 3 'x' "foobar" == "foobar"
862+-- >>> justifyLeft 7 'x' "foo"
863+-- "fooxxxx"
864+--
865+-- >>> justifyLeft 3 'x' "foobar"
866+-- "foobar"
797867justifyLeft :: Int -> Char -> Text -> Text
798868justifyLeft k c t
799869 | len >= k = t
@@ -814,8 +884,11 @@ justifyLeft k c t
814884--
815885-- Examples:
816886--
817−-- > justifyRight 7 'x' "bar" == "xxxxbar"
818−-- > justifyRight 3 'x' "foobar" == "foobar"
887+-- >>> justifyRight 7 'x' "bar"
888+-- "xxxxbar"
889+--
890+-- >>> justifyRight 3 'x' "foobar"
891+-- "foobar"
819892justifyRight :: Int -> Char -> Text -> Text
820893justifyRight k c t
821894 | len >= k = t
@@ -829,7 +902,8 @@ justifyRight k c t
829902--
830903-- Examples:
831904--
832−-- > center 8 'x' "HS" = "xxxHSxxx"
905+-- >>> center 8 'x' "HS"
906+-- "xxxHSxxx"
833907center :: Int -> Char -> Text -> Text
834908center k c t
835909 | len >= k = t
@@ -844,6 +918,14 @@ center k c t
844918-- of its 'Text' argument. Note that this function uses 'pack',
845919-- 'unpack', and the list version of transpose, and is thus not very
846920-- efficient.
921+--
922+-- Examples:
923+--
924+-- >>> transpose ["green","orange"]
925+-- ["go","rr","ea","en","ng","e"]
926+--
927+-- >>> transpose ["blue","red"]
928+-- ["br","le","ud","e"]
847929transpose :: [Text] -> [Text]
848930transpose ts = P.map pack (L.transpose (P.map unpack ts))
849931
@@ -1088,7 +1170,10 @@ iterN n t@(Text _arr _off len) = loop 0 0
10881170--
10891171-- Examples:
10901172--
1091−-- > takeEnd 3 "foobar" == "bar"
1173+-- >>> takeEnd 3 "foobar"
1174+-- "bar"
1175+--
1176+-- @since 1.1.1.0
10921177takeEnd :: Int -> Text -> Text
10931178takeEnd n t@(Text arr off len)
10941179 | n <= 0 = empty
@@ -1099,8 +1184,8 @@ takeEnd n t@(Text arr off len)
10991184iterNEnd :: Int -> Text -> Int
11001185iterNEnd n t@(Text _arr _off len) = loop (len-1) n
11011186 where loop i !m
1187+ | m <= 0 = i+1
11021188 | i <= 0 = 0
1103− | m <= 1 = i
11041189 | otherwise = loop (i+d) (m-1)
11051190 where d = reverseIter_ t i
11061191
@@ -1127,7 +1212,10 @@ drop n t@(Text arr off len)
11271212--
11281213-- Examples:
11291214--
1130−-- > dropEnd 3 "foobar" == "foo"
1215+-- >>> dropEnd 3 "foobar"
1216+-- "foo"
1217+--
1218+-- @since 1.1.1.0
11311219dropEnd :: Int -> Text -> Text
11321220dropEnd n t@(Text arr off len)
11331221 | n <= 0 = t
@@ -1157,7 +1245,10 @@ takeWhile p t@(Text arr off len) = loop 0
11571245-- satisfy @p@. Subject to fusion.
11581246-- Examples:
11591247--
1160−-- > takeWhileEnd (=='o') "foo" == "oo"
1248+-- >>> takeWhileEnd (=='o') "foo"
1249+-- "oo"
1250+--
1251+-- @since 1.2.2.0
11611252takeWhileEnd :: (Char -> Bool) -> Text -> Text
11621253takeWhileEnd p t@(Text arr off len) = loop (len-1) len
11631254 where loop !i !l | l <= 0 = t
@@ -1196,7 +1287,8 @@ dropWhile p t@(Text arr off len) = loop 0 0
11961287--
11971288-- Examples:
11981289--
1199−-- > dropWhileEnd (=='.') "foo..." == "foo"
1290+-- >>> dropWhileEnd (=='.') "foo..."
1291+-- "foo"
12001292dropWhileEnd :: (Char -> Bool) -> Text -> Text
12011293dropWhileEnd p t@(Text arr off len) = loop (len-1) len
12021294 where loop !i !l | l <= 0 = empty
@@ -1314,9 +1406,14 @@ tails t | null t = [empty]
13141406--
13151407-- Examples:
13161408--
1317−-- > splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
1318−-- > splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""]
1319−-- > splitOn "x" "x" == ["",""]
1409+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"
1410+-- ["a","b","d","e"]
1411+--
1412+-- >>> splitOn "aaa" "aaaXaaaXaaaXaaa"
1413+-- ["","X","X","X",""]
1414+--
1415+-- >>> splitOn "x" "x"
1416+-- ["",""]
13201417--
13211418-- and
13221419--
@@ -1352,8 +1449,11 @@ splitOn pat@(Text _ _ l) src@(Text arr off len)
13521449-- resulting components do not contain the separators. Two adjacent
13531450-- separators result in an empty component in the output. eg.
13541451--
1355−-- > split (=='a') "aabbaca" == ["","","bb","c",""]
1356−-- > split (=='a') "" == [""]
1452+-- >>> split (=='a') "aabbaca"
1453+-- ["","","bb","c",""]
1454+--
1455+-- >>> split (=='a') ""
1456+-- [""]
13571457split :: (Char -> Bool) -> Text -> [Text]
13581458split _ t@(Text _off _arr 0) = [t]
13591459split p t = loop t
@@ -1366,8 +1466,11 @@ split p t = loop t
13661466-- element may be shorter than the other chunks, depending on the
13671467-- length of the input. Examples:
13681468--
1369−-- > chunksOf 3 "foobarbaz" == ["foo","bar","baz"]
1370−-- > chunksOf 4 "haskell.org" == ["hask","ell.","org"]
1469+-- >>> chunksOf 3 "foobarbaz"
1470+-- ["foo","bar","baz"]
1471+--
1472+-- >>> chunksOf 4 "haskell.org"
1473+-- ["hask","ell.","org"]
13711474chunksOf :: Int -> Text -> [Text]
13721475chunksOf k = go
13731476 where
@@ -1412,8 +1515,11 @@ filter p t = unstream (S.filter p (stream t))
14121515--
14131516-- Examples:
14141517--
1415−-- > breakOn "::" "a::b::c" ==> ("a", "::b::c")
1416−-- > breakOn "/" "foobar" ==> ("foobar", "")
1518+-- >>> breakOn "::" "a::b::c"
1519+-- ("a","::b::c")
1520+--
1521+-- >>> breakOn "/" "foobar"
1522+-- ("foobar","")
14171523--
14181524-- Laws:
14191525--
@@ -1441,7 +1547,8 @@ breakOn pat src@(Text arr off len)
14411547-- up to and including the last match of @needle@. The second is the
14421548-- remainder of @haystack@, following the match.
14431549--
1444−-- > breakOnEnd "::" "a::b::c" ==> ("a::b::", "c")
1550+-- >>> breakOnEnd "::" "a::b::c"
1551+-- ("a::b::","c")
14451552breakOnEnd :: Text -> Text -> (Text, Text)
14461553breakOnEnd pat src = (reverse b, reverse a)
14471554 where (a,b) = breakOn (reverse pat) (reverse src)
@@ -1456,10 +1563,11 @@ breakOnEnd pat src = (reverse b, reverse a)
14561563--
14571564-- Examples:
14581565--
1459−-- > breakOnAll "::" ""
1460−-- > ==> []
1461−-- > breakOnAll "/" "a/b/c/"
1462−-- > ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]
1566+-- >>> breakOnAll "::" ""
1567+-- []
1568+--
1569+-- >>> breakOnAll "/" "a/b/c/"
1570+-- [("a","/b/c/"),("a/b","/c/"),("a/b/c","/")]
14631571--
14641572-- In (unlikely) bad cases, this function's time complexity degrades
14651573-- towards /O(n*m)/.
@@ -1658,9 +1766,14 @@ isInfixOf needle haystack
16581766--
16591767-- Examples:
16601768--
1661−-- > stripPrefix "foo" "foobar" == Just "bar"
1662−-- > stripPrefix "" "baz" == Just "baz"
1663−-- > stripPrefix "foo" "quux" == Nothing
1769+-- >>> stripPrefix "foo" "foobar"
1770+-- Just "bar"
1771+--
1772+-- >>> stripPrefix "" "baz"
1773+-- Just "baz"
1774+--
1775+-- >>> stripPrefix "foo" "quux"
1776+-- Nothing
16641777--
16651778-- This is particularly useful with the @ViewPatterns@ extension to
16661779-- GHC, as follows:
@@ -1685,9 +1798,14 @@ stripPrefix p@(Text _arr _off plen) t@(Text arr off len)
16851798--
16861799-- Examples:
16871800--
1688−-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1689−-- > commonPrefixes "veeble" "fetzer" == Nothing
1690−-- > commonPrefixes "" "baz" == Nothing
1801+-- >>> commonPrefixes "foobar" "fooquux"
1802+-- Just ("foo","bar","quux")
1803+--
1804+-- >>> commonPrefixes "veeble" "fetzer"
1805+-- Nothing
1806+--
1807+-- >>> commonPrefixes "" "baz"
1808+-- Nothing
16911809commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
16921810commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
16931811 where
@@ -1704,9 +1822,14 @@ commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
17041822--
17051823-- Examples:
17061824--
1707−-- > stripSuffix "bar" "foobar" == Just "foo"
1708−-- > stripSuffix "" "baz" == Just "baz"
1709−-- > stripSuffix "foo" "quux" == Nothing
1825+-- >>> stripSuffix "bar" "foobar"
1826+-- Just "foo"
1827+--
1828+-- >>> stripSuffix "" "baz"
1829+-- Just "baz"
1830+--
1831+-- >>> stripSuffix "foo" "quux"
1832+-- Nothing
17101833--
17111834-- This is particularly useful with the @ViewPatterns@ extension to
17121835-- GHC, as follows:
@@ -1753,3 +1876,12 @@ copy (Text arr off len) = Text (A.run go) 0 len
17531876 marr <- A.new len
17541877 A.copyI marr 0 arr off len
17551878 return marr
1879+
1880+
1881+-------------------------------------------------
1882+-- NOTE: the named chunk below used by doctest;
1883+-- verify the doctests via `doctest -fobject-code Data/Text.hs`
1884+
1885+-- $setup
1886+-- >>> :set -XOverloadedStrings
1887+-- >>> import qualified Data.Text as T