on master help sign in
Add `unsnoc` to Data.Text and Data.Text.Lazy

Closes #171.

commit40a31689b03cbd3d181c6a9f95b9bac5a06ad56c authorBrian Chen <brian.chxn@gmail.com> dateTue 7 Mar 2017, 16:11 (10 years ago) parent831626d
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
@@ -561,6 +562,15 @@ init Empty = emptyError "init"
561562 unstream (S.init (stream t)) = init t
562563 #-}
563564
565+-- | /O(n\/c)/ Returns the 'init' and 'last' of a 'Text', or 'Nothing' if
566+-- empty.
567+--
568+-- * It is no faster than using 'init' and 'last'.
569+unsnoc :: Text -> Maybe (Text, Char)
570+unsnoc Empty = Nothing
571+unsnoc ts@(Chunk _ _) = Just (init ts, last ts)
572+{-# INLINE unsnoc #-}
573+
564574-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
565575-- fusion.
566576null :: 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)
@@ -230,6 +230,13 @@ sf_uncons p = (uncons . L.filter p) `eqP`
230230 (fmap (second unpackS) . S.uncons . S.filter p)
231231t_uncons = uncons `eqP` (fmap (second unpackS) . T.uncons)
232232tl_uncons = uncons `eqP` (fmap (second unpackS) . TL.uncons)
233+
234+unsnoc xs@(_:_) = Just (init xs, last xs)
235+unsnoc [] = Nothing
236+
237+t_unsnoc = unsnoc `eqP` (fmap (first unpackS) . T.unsnoc)
238+tl_unsnoc = unsnoc `eqP` (fmap (first unpackS) . TL.unsnoc)
239+
233240s_head = head `eqP` S.head
234241sf_head p = (head . L.filter p) `eqP` (S.head . S.filter p)
235242t_head = head `eqP` T.head
@@ -976,6 +983,8 @@ tests =
976983 testProperty "sf_uncons" sf_uncons,
977984 testProperty "t_uncons" t_uncons,
978985 testProperty "tl_uncons" tl_uncons,
986+ testProperty "t_unsnoc" t_unsnoc,
987+ testProperty "tl_unsnoc" tl_unsnoc,
979988 testProperty "s_head" s_head,
980989 testProperty "sf_head" sf_head,
981990 testProperty "t_head" t_head,