Commits

Bryan O'Sullivan  committed 7be5ef9

Implement and test lazy last

  • Participants
  • Parent commits f2be691

Comments (0)

Files changed (2)

File Data/Text/Lazy.hs

     , append
     , uncons
     , head
-    -- , last
+    , last
     -- , tail
     -- , init
     -- , null
                 Read(..), Show(..),
                 (&&), (||), (+), (-), (.), ($),
                 not, return, otherwise)
+import qualified Prelude as P
 import Data.String (IsString(..))
 import qualified Data.Text as T
 import qualified Data.Text.Fusion as S
 head t = S.head (stream t)
 {-# INLINE head #-}
 
+-- | /O(1)/ Returns the last character of a 'Text', which must be
+-- non-empty.  Subject to array fusion.
+last :: Text -> Char
+last Empty        = emptyError "last"
+last (Chunk t ts) = go t ts
+    where go _ (Chunk t' ts') = go t' ts'
+          go t Empty          = T.last t
+{-# INLINE [1] last #-}
+
+{-# RULES
+"LAZY TEXT last -> fused" [~1] forall t.
+    last t = S.last (stream t)
+"LAZY TEXT last -> unfused" [1] forall t.
+    S.last (stream t) = last t
+  #-}
+
 -- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
 -- prefix of @t@ of length @n@, and whose second is the remainder of
 -- the string. It is equivalent to @('take' n t, 'drop' n t)@.
              | otherwise = let (ts',ts'') = loop (n - len) ts
                            in (Chunk t ts', ts'')
              where len = T.length t
+
+emptyError :: String -> a
+emptyError fun = P.error ("Data.Text.Lazy." ++ fun ++ ": empty input")

File tests/Properties.hs

 prop_S_head            = head   `eqEP` S.head
 prop_T_head            = head   `eqEP` T.head
 prop_TL_head           = head   `eqEP` TL.head
+prop_S_last            = last   `eqEP` S.last
 prop_T_last            = last   `eqEP` T.last
-prop_T_lastS           = last   `eqEP` (S.last . S.stream)
+prop_TL_last           = last   `eqEP` TL.last
 prop_T_tail            = tail   `eqEP` (unpackT . T.tail)
 prop_T_tailS           = tail   `eqEP` (unpackT . S.unstream . S.tail . S.stream)
 prop_T_init            = init   `eqEP` (unpackT . T.init)
   ("prop_S_head", mytest prop_S_head),
   ("prop_T_head", mytest prop_T_head),
   ("prop_TL_head", mytest prop_TL_head),
+  ("prop_S_last", mytest prop_S_last),
   ("prop_T_last", mytest prop_T_last),
-  ("prop_T_lastS", mytest prop_T_lastS),
+  ("prop_TL_last", mytest prop_TL_last),
   ("prop_T_tail", mytest prop_T_tail),
   ("prop_T_tailS", mytest prop_T_tailS),
   ("prop_T_init", mytest prop_T_init),