on master help sign in
Merge
commit240e1a58e2c0cce5b177e3bc30139b905b1060a6 authorBryan O'Sullivan <bos@serpentine.com> dateTue 27 Jun 2017, 01:23 (9 years ago) parent9e6efb2b42b0dd
3 files changed+32−1
Data/Text.hs+12 Data/Text/Lazy.hs+10 tests/Tests/Properties.hs+10−1
Data/Text.hs+12
@@ -60,6 +60,7 @@ module Data.Text
6060 , snoc
6161 , append
6262 , uncons
63+ , unsnoc
6364 , head
6465 , last
6566 , tail
@@ -545,6 +546,17 @@ init (Text arr off len) | len <= 0 = emptyError "init"
545546 unstream (S.init (stream t)) = init t
546547 #-}
547548
549+-- | /O(1)/ Returns all but the last character and the last character of a
550+-- 'Text', or 'Nothing' if empty.
551+unsnoc :: Text -> Maybe (Text, Char)
552+unsnoc (Text arr off len)
553+ | len <= 0 = Nothing
554+ | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
555+ | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
556+ where n = A.unsafeIndex arr (off+len-1)
557+ n0 = A.unsafeIndex arr (off+len-2)
558+{-# INLINE [1] unsnoc #-}
559+
548560-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
549561-- fusion.
550562null :: Text -> Bool
Data/Text/Lazy.hs+10
@@ -68,6 +68,7 @@ module Data.Text.Lazy
6868 , snoc
6969 , append
7070 , uncons
71+ , unsnoc
7172 , head
7273 , last
7374 , tail
@@ -559,6 +560,15 @@ init Empty = emptyError "init"
559560 unstream (S.init (stream t)) = init t
560561 #-}
561562
563+-- | /O(n\/c)/ Returns the 'init' and 'last' of a 'Text', or 'Nothing' if
564+-- empty.
565+--
566+-- * It is no faster than using 'init' and 'last'.
567+unsnoc :: Text -> Maybe (Text, Char)
568+unsnoc Empty = Nothing
569+unsnoc ts@(Chunk _ _) = Just (init ts, last ts)
570+{-# INLINE unsnoc #-}
571+
562572-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
563573-- fusion.
564574null :: Text -> Bool
tests/Tests/Properties.hs+10−1
@@ -9,7 +9,7 @@ module Tests.Properties
99 ) where
1010
1111import Control.Applicative ((<$>), (<*>))
12−import Control.Arrow ((***), second)
12+import Control.Arrow ((***), first, second)
1313import Data.Bits ((.&.))
1414import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isLetter, isUpper, ord)
1515import Data.Int (Int8, Int16, Int32, Int64)
@@ -232,6 +232,13 @@ sf_uncons p = (uncons . L.filter p) `eqP`
232232 (fmap (second unpackS) . S.uncons . S.filter p)
233233t_uncons = uncons `eqP` (fmap (second unpackS) . T.uncons)
234234tl_uncons = uncons `eqP` (fmap (second unpackS) . TL.uncons)
235+
236+unsnoc xs@(_:_) = Just (init xs, last xs)
237+unsnoc [] = Nothing
238+
239+t_unsnoc = unsnoc `eqP` (fmap (first unpackS) . T.unsnoc)
240+tl_unsnoc = unsnoc `eqP` (fmap (first unpackS) . TL.unsnoc)
241+
235242s_head = head `eqP` S.head
236243sf_head p = (head . L.filter p) `eqP` (S.head . S.filter p)
237244t_head = head `eqP` T.head
@@ -991,6 +998,8 @@ tests =
991998 testProperty "sf_uncons" sf_uncons,
992999 testProperty "t_uncons" t_uncons,
9931000 testProperty "tl_uncons" tl_uncons,
1001+ testProperty "t_unsnoc" t_unsnoc,
1002+ testProperty "tl_unsnoc" tl_unsnoc,
9941003 testProperty "s_head" s_head,
9951004 testProperty "sf_head" sf_head,
9961005 testProperty "t_head" t_head,