on master help sign in
Replace isPrefix implementation with streamed version
aa77840Bryan O'Sullivan
Data/Text.hs+9−6
@@ -837,13 +837,16 @@ unwords = intercalate (singleton ' ')
837{-# INLINE unwords #-}
837{-# INLINE unwords #-}
838
838
839isPrefixOf :: Text -> Text -> Bool
839isPrefixOf :: Text -> Text -> Bool
840−isPrefixOf a@(Text _ _ alen) b@(Text _ _ blen) = alen <= blen && loop 0 0
840+isPrefixOf a@(Text _ _ alen) b@(Text _ _ blen) =
841− where loop !i !j | i >= alen = True
841+ alen <= blen && S.isPrefixOf (stream a) (stream b)
842− | c == e = loop (i+d) (j+f)
843− | otherwise = False
844− where (c,d) = iter a i
845− (e,f) = iter b j
846{-# INLINE [1] isPrefixOf #-}
842{-# INLINE [1] isPrefixOf #-}
847
843
844+{-# RULES
845+"TEXT isPrefixOf -> fused" [~1] forall s t.
846+ isPrefixOf s t = S.isPrefixOf (stream s) (stream t)
847+"TEXT isPrefixOf -> unfused" [1] forall s t.
848+ S.isPrefixOf (stream s) (stream t) = isPrefixOf s t
849+ #-}
850+
848errorEmptyList :: String -> a
851errorEmptyList :: String -> a
849errorEmptyList fun = error ("Data.Text." ++ fun ++ ": empty list")
852errorEmptyList fun = error ("Data.Text." ++ fun ++ ": empty list")
Data/Text/Fusion.hs+17
@@ -79,6 +79,9 @@ module Data.Text.Fusion
79 , takeWhile
79 , takeWhile
80 , dropWhile
80 , dropWhile
81
81
82+ -- * Predicates
83+ , isPrefixOf
84+
82 -- * Searching
85 -- * Searching
83 , elem
86 , elem
84 , filter
87 , filter
@@ -683,6 +686,19 @@ dropWhile p (Stream next0 s0 len) = Stream next (S1 :!: s0) len
683 Yield x s' -> Yield x (S2 :!: s')
686 Yield x s' -> Yield x (S2 :!: s')
684{-# INLINE [0] dropWhile #-}
687{-# INLINE [0] dropWhile #-}
685
688
689+isPrefixOf :: (Eq a) => Stream a -> Stream a -> Bool
690+isPrefixOf (Stream next1 s1 _) (Stream next2 s2 _) = loop (next1 s1) (next2 s2)
691+ where
692+ loop Done _ = True
693+ loop _ Done = False
694+ loop (Skip s1') (Skip s2') = loop (next1 s1') (next2 s2')
695+ loop (Skip s1') x2 = loop (next1 s1') x2
696+ loop x1 (Skip s2') = loop x1 (next2 s2')
697+ loop (Yield x1 s1') (Yield x2 s2') = x1 == x2 &&
698+ loop (next1 s1') (next2 s2')
699+{-# INLINE [0] isPrefixOf #-}
700+{-# SPECIALISE isPrefixOf :: Stream Char -> Stream Char -> Bool #-}
701+
686-- ----------------------------------------------------------------------------
702-- ----------------------------------------------------------------------------
687-- * Searching
703-- * Searching
688
704
@@ -811,5 +827,6 @@ zipWith f (Stream next0 sa0 len1) (Stream next1 sb0 len2) = Stream next (sa0 :!:
811 Yield b sb' -> Yield (f a b) (sa' :!: sb' :!: Nothing)
827 Yield b sb' -> Yield (f a b) (sa' :!: sb' :!: Nothing)
812{-# INLINE [0] zipWith #-}
828{-# INLINE [0] zipWith #-}
813
829
830+
814errorEmptyList :: String -> a
831errorEmptyList :: String -> a
815errorEmptyList fun = error ("Data.Text.Fusion." ++ fun ++ ": empty list")
832errorEmptyList fun = error ("Data.Text.Fusion." ++ fun ++ ": empty list")
tests/Properties.hs+2
@@ -141,6 +141,7 @@ prop_unlines = L.unlines `eq` (unpack . T.unlines . map pack)
141prop_unwords = L.unwords `eq` (unpack . T.unwords . map pack)
141prop_unwords = L.unwords `eq` (unpack . T.unwords . map pack)
142
142
143prop_isPrefixOf s = L.isPrefixOf s`eqP` T.isPrefixOf (pack s)
143prop_isPrefixOf s = L.isPrefixOf s`eqP` T.isPrefixOf (pack s)
144+prop_isPrefixOfS s = L.isPrefixOf s`eqP` (S.isPrefixOf (stream $ pack s) . stream)
144
145
145prop_elem c = L.elem c `eqP` T.elem c
146prop_elem c = L.elem c `eqP` T.elem c
146prop_filter p = L.filter p `eqP` (unpack . T.filter p)
147prop_filter p = L.filter p `eqP` (unpack . T.filter p)
@@ -238,6 +239,7 @@ tests = [
238 ("prop_unwords", mytest prop_unwords),
239 ("prop_unwords", mytest prop_unwords),
239
240
240 ("prop_isPrefixOf", mytest prop_isPrefixOf),
241 ("prop_isPrefixOf", mytest prop_isPrefixOf),
242+ ("prop_isPrefixOfS", mytest prop_isPrefixOfS),
241
243
242 ("prop_elem", mytest prop_elem),
244 ("prop_elem", mytest prop_elem),
243 ("prop_filter", mytest prop_filter),
245 ("prop_filter", mytest prop_filter),