Bryan O'Sullivan avatar Bryan O'Sullivan committed 46c1491

Fix a bug in unfoldrN, add sensible tests

Comments (0)

Files changed (3)

Data/Text/Fusion.hs

 -- 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 = Stream next (0 :!: s0) (n*2)
+unfoldrN n f s0 | n <  0    = empty
+                | otherwise = Stream next (0 :!: s0) (n*2)
     where
       {-# INLINE next #-}
       next (z :!: s) = case f s of

tests/Properties.hs

 prop_scanl f z       = L.scanl f z   `eqP`  (unpack . T.scanl f z)
 
 prop_replicate n     = L.replicate n `eq`   (unpack . T.replicate n)
-prop_unfoldr f       = L.unfoldr f   `eq`   (unpack . T.unfoldr f)
-    where types = f :: Int -> Maybe (Char,Int)
-prop_unfoldrN n f    = (L.take n . L.unfoldr f) `eq` (unpack . T.unfoldrN n f)
-    where types = f :: Int -> Maybe (Char,Int)
+prop_unfoldr n       = L.unfoldr f   `eq`   (unpack . T.unfoldr f)
+    where f c | fromEnum c * 100 > n = Nothing
+              | otherwise            = Just (c, succ c)
+
+prop_unfoldrN n m    = (L.take n . L.unfoldr f) `eq` (unpack . T.unfoldrN n f)
+    where f c | fromEnum c * 100 > m = Nothing
+              | otherwise            = Just (c, succ c)
 
 prop_take n          = L.take n      `eqP` (unpack . T.take n)
 prop_drop n          = L.drop n      `eqP` (unpack . T.drop n)
   ("prop_scanl", mytest prop_scanl),
 
   ("prop_replicate", mytest prop_replicate),
---("prop_unfoldr", mytest prop_unfoldr),
---("prop_unfoldrN", mytest prop_unfoldrN),
+  ("prop_unfoldr", mytest prop_unfoldr),
+  ("prop_unfoldrN", mytest prop_unfoldrN),
 
   ("prop_take", mytest prop_take),
   ("prop_drop", mytest prop_drop),

tests/QuickCheckUtils.hs

 module QuickCheckUtils where
 
 import Data.List
+import Data.Word
 import qualified Data.Text as T
 import System.IO
 import System.Random
 import Test.QuickCheck
 
+integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
+integralRandomR  (a,b) g = case randomR (fromIntegral a :: Integer,
+                                         fromIntegral b :: Integer) g of
+                            (x,g) -> (fromIntegral x, g)
+
+instance Random Word16 where
+  randomR = integralRandomR
+  random  = randomR (minBound,maxBound)
+
+instance Arbitrary Word16 where
+    arbitrary     = choose (minBound,maxBound)
+    coarbitrary c = variant (fromEnum c `rem` 4)
+
 instance Arbitrary Char where
-    arbitrary    = oneof [choose ('\0','\55295'), choose ('\57334','\1114111')]
+    arbitrary     = oneof [choose ('\0','\55295'), choose ('\57334','\1114111')]
     coarbitrary c = variant (fromEnum c `rem` 4)
 
 instance Arbitrary T.Text where
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.