on master help sign in
Implement and test lazy last

--HG-- extra : convert_revision : 8b368bc3e5adff49421f68d593db8eaf6103e154

commitd581176b55d026cceef0c62d65166d6467fbe597 authorBryan O'Sullivan <bos@serpentine.com> dateSun 1 Mar 2009, 06:59 (18 years ago) parent99344b7
2 files changed+25−3
Data/Text/Lazy.hs+21−1 tests/Properties.hs+4−2
Data/Text/Lazy.hs+21−1
@@ -45,7 +45,7 @@ module Data.Text.Lazy
4545 , append
4646 , uncons
4747 , head
48− -- , last
48+ , last
4949 -- , tail
5050 -- , init
5151 -- , null
@@ -151,6 +151,7 @@ import Prelude (Char, Bool(..), Functor(..), Int, Maybe(..), String,
151151 Read(..), Show(..),
152152 (&&), (||), (+), (-), (.), ($),
153153 not, return, otherwise)
154+import qualified Prelude as P
154155import Data.String (IsString(..))
155156import qualified Data.Text as T
156157import qualified Data.Text.Fusion as S
@@ -250,6 +251,22 @@ head :: Text -> Char
250251head t = S.head (stream t)
251252{-# INLINE head #-}
252253
254+-- | /O(1)/ Returns the last character of a 'Text', which must be
255+-- non-empty. Subject to array fusion.
256+last :: Text -> Char
257+last Empty = emptyError "last"
258+last (Chunk t ts) = go t ts
259+ where go _ (Chunk t' ts') = go t' ts'
260+ go t Empty = T.last t
261+{-# INLINE [1] last #-}
262+
263+{-# RULES
264+"LAZY TEXT last -> fused" [~1] forall t.
265+ last t = S.last (stream t)
266+"LAZY TEXT last -> unfused" [1] forall t.
267+ S.last (stream t) = last t
268+ #-}
269+
253270-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
254271-- prefix of @t@ of length @n@, and whose second is the remainder of
255272-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
@@ -263,3 +280,6 @@ splitAt = loop
263280 | otherwise = let (ts',ts'') = loop (n - len) ts
264281 in (Chunk t ts', ts'')
265282 where len = T.length t
283+
284+emptyError :: String -> a
285+emptyError fun = P.error ("Data.Text.Lazy." ++ fun ++ ": empty input")
tests/Properties.hs+4−2
@@ -124,8 +124,9 @@ prop_TL_uncons s = uncons `eqP` (fmap (second unpackT) . TL.uncons)
124124prop_S_head = head `eqEP` S.head
125125prop_T_head = head `eqEP` T.head
126126prop_TL_head = head `eqEP` TL.head
127+prop_S_last = last `eqEP` S.last
127128prop_T_last = last `eqEP` T.last
128−prop_T_lastS = last `eqEP` (S.last . S.stream)
129+prop_TL_last = last `eqEP` TL.last
129130prop_T_tail = tail `eqEP` (unpackT . T.tail)
130131prop_T_tailS = tail `eqEP` (unpackT . S.unstream . S.tail . S.stream)
131132prop_T_init = init `eqEP` (unpackT . T.init)
@@ -300,8 +301,9 @@ tests = [
300301 ("prop_S_head", mytest prop_S_head),
301302 ("prop_T_head", mytest prop_T_head),
302303 ("prop_TL_head", mytest prop_TL_head),
304+ ("prop_S_last", mytest prop_S_last),
303305 ("prop_T_last", mytest prop_T_last),
304− ("prop_T_lastS", mytest prop_T_lastS),
306+ ("prop_TL_last", mytest prop_TL_last),
305307 ("prop_T_tail", mytest prop_T_tail),
306308 ("prop_T_tailS", mytest prop_T_tailS),
307309 ("prop_T_init", mytest prop_T_init),