Bryan O'Sullivan avatar Bryan O'Sullivan committed b95676b

Implement and test unfolds

Comments (0)

Files changed (3)

Data/Text/Fusion.hs

     , replicate
     , unfoldr
     , unfoldrN
+    , unfoldrN64
 
     -- * Substrings
     -- ** Breaking strings
     , zipWith
     ) where
 
-import Prelude (Bool(..), Char, Either(..), Eq(..), Maybe(..), Monad(..),
-                Num(..), Ord(..), String, ($), (++), (.), (&&),
+import Prelude (Bool(..), Char, Either(..), Eq(..), Integral, Maybe(..),
+                Monad(..), Num(..), Ord(..), String, ($), (++), (.), (&&),
                 fromIntegral, otherwise)
 import qualified Data.List as L
 import GHC.Exts (Int(..), (+#))
 -- value. However, the length of the result is limited by the
 -- first argument to 'unfoldrN'. This function is more efficient than
 -- 'unfoldr' when the length of the result is known.
-unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Stream Char
-unfoldrN n f s0 | n <  0    = empty
-                | otherwise = Stream next (0 :!: s0) (n*2)
+unfoldrI :: Integral a => a -> (b -> Maybe (Char,b)) -> b -> Stream Char
+unfoldrI n f s0 | n <  0    = empty
+                | otherwise = Stream next (0 :!: s0) (fromIntegral (n*2))
     where
       {-# INLINE next #-}
       next (z :!: s) = case f s of
           Nothing                  -> Done
           Just (w, s') | z >= n    -> Done
                        | otherwise -> Yield w ((z + 1) :!: s')
+{-# INLINE unfoldrI #-}
+
+-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a stream from a seed
+-- value. However, the length of the result is limited by the
+-- first argument to 'unfoldrN'. This function is more efficient than
+-- 'unfoldr' when the length of the result is known.
+unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Stream Char
+unfoldrN n = unfoldrI (fromIntegral n :: Int)
+{-# INLINE [0] unfoldrN #-}
+
+-- | /O(n)/ Like 'unfoldr', 'unfoldrN64' builds a stream from a seed
+-- value. However, the length of the result is limited by the
+-- first argument to 'unfoldrN64'. This function is more efficient than
+-- 'unfoldr' when the length of the result is known.
+unfoldrN64 :: Int64 -> (a -> Maybe (Char,a)) -> a -> Stream Char
+unfoldrN64 n = unfoldrI (fromIntegral n :: Int64)
+{-# INLINE [0] unfoldrN64 #-}
+
 -------------------------------------------------------------------------------
 --  * Substreams
 

Data/Text/Lazy.hs

     , mapAccumR
 
     -- ** Generation and unfolding
-    -- , replicate
-    -- , unfoldr
-    -- , unfoldrN
+    , replicate
+    , unfoldr
+    , unfoldrN
 
     -- * Substrings
 
                         where (s'',y ) = f s' x
                               (s', ys) = mapAccumR f s xs
 
+-- | /O(n)/ 'replicate' @n@ @c@ is a 'Text' of length @n@ with @c@ the
+-- value of every element.
+replicate :: Int -> Char -> Text
+replicate n c = unstream (S.replicate n c)
+{-# INLINE replicate #-}
+
+-- | /O(n)/, where @n@ is the length of the result. The 'unfoldr'
+-- function is analogous to the List 'L.unfoldr'. 'unfoldr' builds a
+-- 'Text' from a seed value. The function takes the element and
+-- returns 'Nothing' if it is done producing the 'Text', otherwise
+-- 'Just' @(a,b)@.  In this case, @a@ is the next 'Char' in the
+-- string, and @b@ is the seed value for further production.
+unfoldr     :: (a -> Maybe (Char,a)) -> a -> Text
+unfoldr f s = unstream (S.unfoldr f s)
+{-# INLINE unfoldr #-}
+
+-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a 'Text' from a seed
+-- value. However, the length of the result should be limited by the
+-- first argument to 'unfoldrN'. This function is more efficient than
+-- 'unfoldr' when the maximum length of the result is known and
+-- correct, otherwise its performance is similar to 'unfoldr'.
+unfoldrN     :: Int64 -> (a -> Maybe (Char,a)) -> a -> Text
+unfoldrN n f s = unstream (S.unfoldrN64 n f s)
+{-# INLINE unfoldrN #-}
+
 -- | /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)@.

tests/Properties.hs

 prop_TL_mapAccumR f z   = L.mapAccumR f z `eqP` (second unpackT . TL.mapAccumR f z)
     where types = f :: Int -> Char -> (Int,Char)
 
-prop_T_replicate n     = L.replicate n `eq`   (unpackT . T.replicate n)
-prop_T_unfoldr n       = L.unfoldr f   `eq`   (unpackT . T.unfoldr f)
-    where f c | fromEnum c * 100 > n = Nothing
-              | otherwise            = Just (c, succ c)
+prop_T_replicate n     = L.replicate n `eq` (unpackT . T.replicate n)
+prop_TL_replicate n    = L.replicate n `eq` (unpackT . TL.replicate n)
 
-prop_T_unfoldrN n m    = (L.take n . L.unfoldr f) `eq` (unpackT . T.unfoldrN n f)
-    where f c | fromEnum c * 100 > m = Nothing
-              | otherwise            = Just (c, succ c)
+unf :: Int -> Char -> Maybe (Char, Char)
+unf n c | fromEnum c * 100 > n = Nothing
+        | otherwise            = Just (c, succ c)
+
+prop_T_unfoldr n       = L.unfoldr (unf n) `eq` (unpackT . T.unfoldr (unf n))
+prop_TL_unfoldr n      = L.unfoldr (unf n) `eq` (unpackT . TL.unfoldr (unf n))
+prop_T_unfoldrN n m    = (L.take n . L.unfoldr (unf m)) `eq`
+                         (unpackT . T.unfoldrN n (unf m))
+prop_TL_unfoldrN n m   = (L.take n . L.unfoldr (unf m)) `eq`
+                         (unpackT . TL.unfoldrN (fromIntegral n) (unf m))
 
 unpack2 :: (Target t) => (t,t) -> (String,String)
 unpack2 = unpackT *** unpackT
   ("prop_TL_mapAccumR", mytest prop_TL_mapAccumR),
 
   ("prop_T_replicate", mytest prop_T_replicate),
+  ("prop_TL_replicate", mytest prop_TL_replicate),
   ("prop_T_unfoldr", mytest prop_T_unfoldr),
+  ("prop_TL_unfoldr", mytest prop_TL_unfoldr),
   ("prop_T_unfoldrN", mytest prop_T_unfoldrN),
+  ("prop_TL_unfoldrN", mytest prop_TL_unfoldrN),
 
   ("prop_T_take", mytest prop_T_take),
   ("prop_T_drop", mytest prop_T_drop),
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.